I have coded a drawing & guessing game simular to skribble.io and I'm using a TCP Socketserver for providing the game information to all connected players. On the client side is a thread running with a while true loop which is constently requesting for the needed information and on the server side is running a while true loop which is receiving the request and giving the right response for that. For serialization of the data I use pickle. When I'm testing my game on my local machine with a running server and some clients everything is working fine but If I'm testing it on my local network or over the internet it's starting to get very laggy on the client side and everything takes a huge amount of time to display the right server information for example a timer which is running in my game isn't updating every second and also the drawing is laggy.
Client Side:
def receive_data():
global connected_clients, client, start, grid, in_game, lobby_id
while True:
try:
if not in_game:
data = network.receive()
if isinstance(data, list): # get connected clients
connected_clients = data
for c in connected_clients: # get current client
if c.uid == client.uid:
client = c
elif data == 'start':
start = True
in_game = True
else:
if not client.drawing:
res = network.get('grid')['grid'] # get grid
grid.update(res)
# get round information
topbar.word = network.get('word')['word'] # get word
client.drawing = network.get('drawing')['drawing']
topbar.time = network.get('time')['time'] # get round time
topbar.round = network.get('round')['round']
response = network.get('clients') # get all connected clients
connected_clients = response['clients']
for c in connected_clients: # get current client
if c.uid == client.uid:
client = c
messages = network.get('chat')['chat'] # get chat
chat.update(messages, client)
except:
pass
Network method get():
def get(self, data): # returns the response for the request
try:
self.client.send(pickle.dumps(data))
buff_size = 4096
data = bytearray()
while True:
chunk = self.client.recv(buff_size)
data += chunk
if len(chunk) < buff_size:
break
return pickle.loads(data)
except Exception as e:
print(e)
Server Side:
def handle_player(self, connection, player):
data = None
send_msg = {}
while True:
try:
try:
data = self.receive(connection)
except:
pass
if not self.in_game: # lobby logic
if data == 'ready':
player.ready = True
self.broadcast(self.players_to_clients())
if self.all_players_ready():
self.broadcast('start')
self.game = Game(self.players)
for p in self.players:
p.set_game(self.game)
self.in_game = True
elif self.in_game: # in game logic
if player.game:
if isinstance(data, list):
player.game.grid.completely_update(data)
elif isinstance(data, dict):
player.game.make_player_guess(player, data['guess'])
if data == 'word':
send_msg['word'] = player.game.round.word
elif data == 'drawing':
player.drawing = player.game.round.player_drawing == player
if player.drawing:
send_msg['drawing'] = True
else:
send_msg['drawing'] = False
elif data == 'clients':
send_msg['clients'] = self.players_to_clients()
elif data == 'time':
send_msg['time'] = player.game.round.draw_time
elif data == 'grid':
send_msg['grid'] = player.game.grid.get_grid()
elif data == 'chat':
send_msg['chat'] = player.game.chat.messages
elif data == 'round':
send_msg['round'] = player.game.round_count
connection.send(pickle.dumps(send_msg))
else:
pass
except socket.error:
print(f'{player.name} disconnected.')
player.game.player_disconnect(player)
if player in self.players:
self.players.remove(player)
if connection in self.connections:
self.connections.remove(connection)
self.broadcast(self.players_to_clients())
break
I got already an idea for a possible solution which is to switch from TCP to UDP and TCP but i don't know how to implement both in a way that I can send all necessary information.
PS: Sorry for any english mistakes and thanks for any help.