1

I've made a server and client using python sockets. The server accepts all the clients and sends each client to a new thread. Each thread gives the client a name (a random integer between 1 and 100) and then sets their values in a dictionary.

The thread sends the dictionary to the client so it can render everything on a Pygame window. The client edits the value based on it's player position and sends the edited dictionary back to the thread which adds the value to the server dictionary.

The server dictionary is shared by all the clients.

My question is, I'm using the "global" python keyword and unless I print it, it doesn't seem to be working. The clients are receiving the values, but for them, only their position is changing. With the print function, the clients are getting everyone's position.

What is going on and is there anyway of doing this without a print function?

server.py:

import socket
import threading
import json
import random
import time

# Set Up
HOST = "localhost"
PORT = 9999
s = socket.socket()
s.bind((HOST, PORT))

print("The server has started and is ready to accept participants!")

# random int: location as list
all_locs = {1: [200, 200], 2: [700, 500]}

def recv_and_send(c, addr):
    random_val = str(random.randrange(1, 101))
    c.send(str(random_val).encode())
    print(f"Yayyy! We have gotten a new connection at {addr} and they have been given a value ({random_val})!")
    c.recv(0)

    while True:
        global all_locs
        
        print(all_locs) # this one
        
        c.send(json.dumps(all_locs).encode())
        received = json.loads(c.recv(2048).decode())
        all_locs = received

s.listen()
while True:
    c, addr = s.accept()
    print(f"A new connection ({addr}) has just been accepted!")
    t = threading.Thread(target=recv_and_send, args=(c, addr,))
    t.start()

client.py

import json
import socket
import json
import pygame
import random

# setting up pygame
pygame.init()
win = pygame.display.set_mode((800, 600))

# setting up sockets
HOST = "localhost"
PORT = 9999
s = socket.socket()
s.connect((HOST, PORT))

print("We have been accepted!")

pos = [random.randrange(100, 700), random.randrange(100, 500)]

random_val = s.recv(2048).decode().split("{")[0]
print(f"Our value is {random_val}!")
s.send(b"")

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    win.fill((0, 0, 0))
    
    keys = pygame.key.get_pressed()

    if keys[pygame.K_w]:
        pos[1] -= 0.2
    elif keys[pygame.K_s]:
        pos[1] += 0.2
    if keys[pygame.K_a]:
        pos[0] -= 0.2
    elif keys[pygame.K_d]:
        pos[0] += 0.2
    pos = [int(p) for p in pos]


    # get the data
    received_data = s.recv(2048)
    received_data = received_data.decode()
    recv_all_locs = json.loads(received_data)

    # change the data
    recv_all_locs[random_val] = pos

    # show the data
    if len(recv_all_locs) > 0:
        for val in recv_all_locs.values():
            pygame.draw.rect(win, (255, 0, 0), (val[0], val[1], 10, 10))
    pygame.display.update()

    #if len(recv_all_locs) == 4:
    #    print(recv_all_locs)

    # send the data
    s.send(json.dumps(recv_all_locs).encode())

pygame.quit()
s.close()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Which `print` function (I assume you meant "print call")? – Selcuk Oct 18 '21 at 05:57
  • In server.py ```print(all_locs)```. Edited it and added a comment so you can find it. –  Oct 18 '21 at 05:59
  • 4
    I feel this will be a problem because of the synchronization. Without a print, you will be immediately submitting the dictionary back. A print call might (because of GIL) make a little time for other threads to update. Try a minimal sleep ? – Kris Oct 18 '21 at 06:00
  • Cool!. Good to know that. Shall I suggest use of a shared dictionary using multiprocessing.manager in python and avoid sockets after all (if its going to be on same machine)? – Kris Oct 18 '21 at 06:13
  • Hi, can you tell us about your protocol, it's not clear to me how the client must do at the beginning of the connections. The client connect and wait for 2048 bytes `random_val = s.recv(2048).decode().split("{")[0]` but in server I don't know how many information is sent `c.send(str(random_val).encode())`, i suppose that `str(random_val).encode()`should have a size of 2048 bytes, which is the amount of bytes that the client is waiting for. – Jorge Omar Medra Oct 20 '21 at 04:00

0 Answers0