Now that we have a new, all receiving and broadcasting chat server, we just need a client to go with it. We have mentioned before that we will hit a problem with our procedural client when trying to listen for both network data and user input at the same time. Well, now that we have some idea of how to employ threads, we can have a go at addressing this. Create a new text file called 2.2-chat_client-multithread.py
and save the following code in it:
import sys, socket, threading import tincanchat HOST = sys.argv[-1] if len(sys.argv) > 1 else '127.0.0.1' PORT = tincanchat.PORT def handle_input(sock): """ Prompt user for message and send it to server """ print("Type messages, enter to send. 'q' to quit") while True: msg = input() # Blocks if msg == 'q': sock.shutdown(socket.SHUT_RDWR) sock.close() break try: tincanchat.send_msg(sock, msg) # Blocks until sent except (BrokenPipeError, ConnectionError): break if __name__ == '__main__': sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((HOST, PORT)) print('Connected to {}:{}'.format(HOST, PORT)) # Create thread for handling user input and message sending thread = threading.Thread(target=handle_input, args=[sock], daemon=True) thread.start() rest = bytes() addr = sock.getsockname() # Loop indefinitely to receive messages from server while True: try: # blocks (msgs, rest) = tincanchat.recv_msgs(sock, rest) for msg in msgs: print(msg) except ConnectionError: print('Connection to server closed') sock.close() break
We've updated our client to honor our new chat protocol by creating a new thread to handle user input and send messages, while handling receiving messages in the main thread. This allows the client to deal with the user input and receive the messages at the same time.
Note that there's no shared state here, so we didn't have to get clever with Queues
or synchronization primitives.
Let's give our new programs a try. Fire up the multithreaded chat server, and then launch at least two clients. If you can, run them in terminals such that you can watch all of them at once. Now, try and send some messages from the clients and see how they are sent to all of the other clients.