import socket class PacketUtility: """The base class of QuickStreamServer and QuickStreamClient.""" @staticmethod def getMyIP(): return socket.gethostbyname(socket.getfqdn()) @staticmethod def getMyDomainName(): return socket.getfqdn() @staticmethod def get_int(socket, int_length = 2): """Get a tuple of ints from THE OTHER SIDE!""" size = b"" message = b"" msg_len = int(0) bytes_recd = int(0) ret = [] while bytes_recd < int_length: size += socket.recv(int_length - bytes_recd) if size == b"": raise RuntimeError("socket connection broken") bytes_recd = len(size) msg_len = int.from_bytes(size, byteorder = "big") bytes_recd = int(0) while bytes_recd < msg_len: message += socket.recv(min(msg_len - bytes_recd, 1024)) if bytes_recd == len(message): # if the message wasn't added to raise RuntimeError("socket connection broken") bytes_recd = len(message) socket.send(bytes_recd.to_bytes(int_length, byteorder = "big")) for i in range(0, int(msg_len), int_length): ret.append(int.from_bytes(message[i:i+int_length], byteorder = "big")) return tuple(ret) @staticmethod def get_str(socket): """get a string from THE OTHER SIDE!""" size = b"" message = b"" msg_len = int(0) bytes_recd = int(0) #ret = [] while bytes_recd < 2: size += socket.recv(2 - bytes_recd) if size == b"": raise RuntimeError("socket connection broken") bytes_recd = len(size) msg_len = int.from_bytes(size, byteorder = "big") bytes_recd = int(0) while bytes_recd < msg_len: message += socket.recv(min(msg_len - bytes_recd, 1024)) if bytes_recd == len(message): raise RuntimeError("socket connection broken") bytes_recd = len(message) socket.send(bytes_recd.to_bytes(2, byteorder = "big")) ret = str(message, "utf-8") return ret @staticmethod def send_int(socket, stuff, int_length = 2): #tuple stuff """Send a tuple of ints to THE OTHER SIDE!""" message = b"" for thing in stuff: message += int(thing).to_bytes(int_length, byteorder = "big") msg_len = len(message) message = msg_len.to_bytes(int_length, byteorder = "big") + message total_sent = 0 while total_sent < msg_len + int_length: total_sent += socket.send(message[total_sent:]) confirm = socket.recv(int_length) if int.from_bytes(confirm, byteorder = "big") == msg_len: return else: raise RuntimeError("incomplete packet sent") @staticmethod def send_str(socket, stuff): """Send a string to THE OTHER SIDE!""" msg_len = len(stuff) message = msg_len.to_bytes(2, byteorder = "big") + bytes(stuff, "utf-8") total_sent = 0 while total_sent < msg_len + 2: total_sent += socket.send(message[total_sent:]) confirm = socket.recv(2) if int.from_bytes(confirm, byteorder = "big") == msg_len: return else: raise RuntimeError("incomplete packet sent") class QuickStreamServer(PacketUtility): """Get a server set up easily! Note: This kind of server is NOT always ideal.""" def __init__(self, port = 1028, expectedClients = 1, ipAddress = ''): """Creates a quick server using the specified port and number of expected clients.""" self.clients = [] # Start with an empty list of clients serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if len(ipAddress) >= 6: address = (ipAddress, port) else: address = (socket.gethostname(), port) serverSocket.bind(address) serverSocket.listen(1) for i in range(expectedClients): self.clients.append(serverSocket.accept()) serverSocket.close() def __del__(self): self.close() def close(self): if self.clients: for i in range(len(self.clients)): self.clients[i][0].close() def getByte(self): """Get a list of byte-size ints from each client.""" ret = [] for i in range(len(self.clients)): ret.append(QuickStreamServer.get_int(self.clients[i][0], 1)) return ret def getShort(self): """Get a list of short ints from each client.""" ret = [] for i in range(len(self.clients)): ret.append(QuickStreamServer.get_int(self.clients[i][0], 2)) return ret def getInt(self): """Get a list of ints from each client.""" ret = [] for i in range(len(self.clients)): ret.append(QuickStreamServer.get_int(self.clients[i][0], 4)) return ret def getLong(self): """Get a list of long ints from each client.""" ret = [] for i in range(len(self.clients)): ret.append(QuickStreamServer.get_int(self.clients[i][0], 8)) return ret def getString(self): """Get a string from each client.""" ret = [] for i in range(len(self.clients)): ret.append(QuickStreamServer.get_str(self.clients[i][0])) return ret def sendByte(self, message): """Send a tuple of byte-size ints to each client.""" if not isinstance(message, tuple): message = tuple(message) for i in range(len(self.clients)): QuickStreamServer.send_int(self.clients[i][0], message, 1) def sendShort(self, message): """Send a tuple of short ints to each client.""" if not isinstance(message, tuple): message = tuple(message) for i in range(len(self.clients)): QuickStreamServer.send_int(self.clients[i][0], message, 2) def sendByte(self, message): """Send a tuple of ints to each client.""" if not isinstance(message, tuple): message = tuple(message) for i in range(len(self.clients)): QuickStreamServer.send_int(self.clients[i][0], message, 4) def sendLong(self, message): """Send a tuple of long ints to each client.""" if not isinstance(message, tuple): message = tuple(message) for i in range(len(self.clients)): QuickStreamServer.send_int(self.clients[i][0], message, 8) def sendString(self, message): """Send a string to each client.""" for i in range(len(self.clients)): QuickStreamServer.send_str(self.clients[i][0], message) class QuickStreamClient(PacketUtility): """Get a client set up easily! Note: This kind of client is NOT always ideal.""" def __init__(self, ipAddress, port = 1028): """Creates a quick client using the specified IP address and port.""" self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server.connect((ipAddress, port)) def __del__(self): if self.server: self.server.close() def close(self): if self.server: self.server.close() def getByte(self): """Get a tuple of byte-size ints from the server.""" return QuickStreamClient.get_int(self.server, 1) def getShort(self): """Get a tuple of short ints from the server.""" return QuickStreamClient.get_int(self.server, 2) def getInt(self): """Get a tuple of ints from the server.""" return QuickStreamClient.get_int(self.server, 4) def getLong(self): """Get a tuple of long ints from the server.""" return QuickStreamClient.get_int(self.server, 8) def getString(self): """Get a string from the server.""" return QuickStreamClient.get_str(self.server) def sendByte(self, message): """Send a tuple of byte-size ints to the server.""" if not isinstance(message, tuple): message = tuple(message) QuickStreamClient.send_int(self.server, message, 1) def sendShort(self, message): """Send a tuple of short ints to the server.""" if not isinstance(message, tuple): message = tuple(message) QuickStreamClient.send_int(self.server, message, 2) def sendInt(self, message): """Send a tuple of ints to the server.""" if not isinstance(message, tuple): message = tuple(message) QuickStreamClient.send_int(self.server, message, 4) def sendLong(self, message): """Send a tuple of long ints to the server.""" if not isinstance(message, tuple): message = tuple(message) QuickStreamClient.send_int(self.server, message, 8) def sendString(self, message): """Send a string to the server.""" QuickStreamClient.send_str(self.server, message) # Legacy support: get_int = PacketUtility.get_int get_str = PacketUtility.get_str send_int = PacketUtility.send_int send_str = PacketUtility.send_str if __name__ == "__main__": print("""packets.py Contents: Class PacketUtility: The base class of QuickStreamServer and QuickStreamClient. Methods: getMyIP() get_int(socket, int_length = 2) get_str(socket) send_int(socket, stuff, int_length = 2) send_str(socket, stuff) Class QuickStreamServer: Get a server set up easily! Note: This kind of server is NOT always ideal. Methods: QuickStreamServer(port, expectedClients = 1, ipAddress = '') getByte() getShort() getInt() getLong() getString() sendByte(message) sendShort(message) sendInt(message) sendLong(message) sendString(message) Fields: clients Class QuickStreamClient: Get a client set up easily! Note: This kind of client is NOT always ideal. Methods: QuickStreamClient(ipAddress, port) getByte() getShort() getInt() getLong() getString() sendByte(message) sendShort(message) sendInt(message) sendLong(message) sendString(message) Fields: server Legacy: get_int(socket, int_length = 2) get_str(socket) send_int(socket, stuff, int_length = 2) send_str(socket, stuff) This module is meant to be imported along with 'socket'.""")