spelling-game-python/packets.py

309 lines
11 KiB
Python
Raw Permalink Normal View History

2016-11-25 11:01:11 -05:00
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 = ''):
2016-11-25 11:01:11 -05:00
"""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:
2016-11-25 11:01:11 -05:00
address = (ipAddress, port)
else:
2016-11-25 11:01:11 -05:00
address = (socket.gethostname(), port)
serverSocket.bind(address)
serverSocket.listen(1)
2016-11-25 11:01:11 -05:00
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()
2016-11-25 11:01:11 -05:00
def getByte(self):
"""Get a list of byte-size ints from each client."""
2016-11-25 11:01:11 -05:00
ret = []
for i in range(len(self.clients)):
ret.append(QuickStreamServer.get_int(self.clients[i][0], 1))
return ret
2016-11-25 11:01:11 -05:00
def getShort(self):
"""Get a list of short ints from each client."""
2016-11-25 11:01:11 -05:00
ret = []
for i in range(len(self.clients)):
ret.append(QuickStreamServer.get_int(self.clients[i][0], 2))
return ret
2016-11-25 11:01:11 -05:00
def getInt(self):
"""Get a list of ints from each client."""
2016-11-25 11:01:11 -05:00
ret = []
for i in range(len(self.clients)):
ret.append(QuickStreamServer.get_int(self.clients[i][0], 4))
return ret
2016-11-25 11:01:11 -05:00
def getLong(self):
"""Get a list of long ints from each client."""
2016-11-25 11:01:11 -05:00
ret = []
for i in range(len(self.clients)):
ret.append(QuickStreamServer.get_int(self.clients[i][0], 8))
return ret
2016-11-25 11:01:11 -05:00
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
2016-11-25 11:01:11 -05:00
def sendByte(self, message):
"""Send a tuple of byte-size ints to each client."""
if not isinstance(message, tuple): message = tuple(message)
2016-11-25 11:01:11 -05:00
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)
2016-11-25 11:01:11 -05:00
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)
2016-11-25 11:01:11 -05:00
for i in range(len(self.clients)):
QuickStreamServer.send_int(self.clients[i][0], message, 4)
def sendLong(self, message):
2016-11-25 11:01:11 -05:00
"""Send a tuple of long ints to each client."""
if not isinstance(message, tuple): message = tuple(message)
2016-11-25 11:01:11 -05:00
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):
2016-11-25 11:01:11 -05:00
"""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))
2016-11-25 11:01:11 -05:00
def __del__(self):
if self.server:
self.server.close()
def close(self):
if self.server:
self.server.close()
2016-11-25 11:01:11 -05:00
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)
2016-11-25 11:01:11 -05:00
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)
2016-11-25 11:01:11 -05:00
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)
2016-11-25 11:01:11 -05:00
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)
2016-11-25 11:01:11 -05:00
QuickStreamClient.send_int(self.server, message, 8)
def sendString(self, message):
"""Send a string to the server."""
QuickStreamClient.send_str(self.server, message)
2016-11-25 11:01:11 -05:00
# 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'.""")