Search code examples
pythonmultithreadingsocketsnetwork-programmingclient

ONLY one client receive message in multiple client's server


My target is print the message from function result on the client's screen. But only ONE client can received the message...


The part of client.py is here

def PlayGame(clientSocket, msg):
invalid = "NO!"
if ("/guess " in msg):
    msg1 = msg.split(" ")[1]
    print("Hi1\n")
    if msg1 == "true" or msg1 == "false":
        print("Hi11")
        clientSocket.send(msg1.encode())
        print(clientSocket.recv(1024).decode())
        print("!")
        return '1'

    else:
        clientSocket.send(invalid.encode())
        print(clientSocket.recv(1024).decode())
        print("2")
        return '2'
elif msg == "":
    return '2'
else:
    clientSocket.send(invalid.encode())
    print(clientSocket.recv(1024).decode())
    print("3")
    return '2'

def main(argv):
            msg=""
            while (PlayGame(clientSocket, msg)!=1):
                msg = input()

Any part of the server.py

guess_box = []
guess = bool(random.randint(0, 1))
    def result(connectionSocket, guess_box,  addr, addr_l):
        a = 0
        if(guess_box[0] == guess_box[1]):
            msg = "Tie!!"
            connectionSocket.send(msg.encode())
            return '2'
        elif(guess_box[0] == guess):
            msg = "Player 1 Wins!"
            a+=1
            connectionSocket.send(msg.encode())
            return '2'
        elif(guess_box[1] == guess):
            msg = "Player 2 Wins!"
            a+=1
            connectionSocket.send(msg.encode())
            return '2'
    
    def TF(connectionSocket, var, guess_box, addr, addr_l):
        msg = connectionSocket.recv(1024).decode()
        print("recv:",msg)
        if(msg == 'true'):
            msg = 'True'
            var = str(var)
            msg = bool(msg == var)
            guess_box.append(msg)
            return 'ok'
        elif(msg == 'false'):
            msg = 'False'
            var = str(var)
            msg = bool(msg == var)
            guess_box.append(msg)
            return 'ok'
        else:
            print(msg)
            statement = "4002 Unrecognized message!!"
            connectionSocket.send(statement.encode())
            return 'again'
class ServerThread(threading.Thread):
    def __init__(self, client):
        threading.Thread.__init__(self)
        self.client = client

    def run(self):
    ...
    print("guess is:", guess)
    
                    while (len(guess_box) != 2):
                        TF(connectionSocket, guess, guess_box, addr, addr_l)
    
                    print("start")
                    result(connectionSocket, guess_box, addr, addr_l)
    ...

Solution

  • Regarding only the one problem you address:

    print the message from function result on the client's screen. But only ONE client can received the message

    The problem comes from the use of a different thread for each client. The thread which receives a guess as first stays in its

                            while (len(guess_box) != 2):
                                print(guess_box)
                                TF(connectionSocket, guess, guess_box)
    

    loop and waits for another message, which doesn't come. The thread which receives a guess as second sends the result to its own client only.

    I don't think there's a sensible way to fix this while keeping this dthreaded approach.

    Can I change the structure of my code by using those functions I implemented?

    Here's a substitute for the while True loop in server_run that doesn't require changes in those functions other than server_run.

            from select import select
            connections = []
            room_connection = {}
            for reads in iter(lambda: select([serverSocket]+connections, [], [])[0], []):
                for ready in reads: # for each socket which select reports is readable
                    if ready == serverSocket:   # it's the server socket, accept new client
                        connectionSocket, addr = serverSocket.accept()
                        connections.append(connectionSocket)# store the connection socket
                        while RecvFromClient(connectionSocket) == "NO": pass
                    else:           # message (or disconnect) from a client
                        try: var = GameHallMsg(ready, ready, connections)
                        except socket.error: var = 'bye'
                        if var == 'bye':    # client finished, remove from list
                            connections.remove(ready)
                            ready.close()
                        elif var == 'wait': # store first player's connection
                            room_connection[current_rm_num.pop()] = ready
                        elif var == 'NO':
                            rtn_msg_4 = "4002 Unrecognized message"
                            ready.send(rtn_msg_4.encode())
                        elif var == 'jump':
                            readyroom = current_rm_num.pop()
                            # find and notify other player in the room
                            other = room_connection.pop(readyroom)
                            rtn_msg_2 = "3012 Game started. Please guess true or false"
                            other.send(rtn_msg_2.encode())
                            print("guess is:", guess)
                            # query and inform both players
                            guess_box = []
                            while TF(ready, True, guess_box) != 'ok': pass
                            while TF(other, True, guess_box) != 'ok': pass
                            result(ready, guess_box, ('', 0), [0])
                            result(other, guess_box, ('', 1), [0, 1])
                            room[readyroom] = 0