Hi I am trying to create a very simple peer-to-peer chatting program in python. The first user can runs the server.py program below to bind to a socket.
import sys import socket import select import threading # Bind to socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(('127.0.0.1', 11111)) s.listen() def chat(conn, addr): # Set blocking to false so that program can send and receive messages at the same time conn.setblocking(0) # Receive messages using select while conn in select.select([conn], [], [], 0)[0]: text = conn.recv(4096) if text: print("{}: {}".format(addr, text)) else: return # get user input and send message while True: msg = input(">>>") conn.send(msg.encode()) if __name__ == '__main__': ## Accept connections and start new thread (conn, addr) = s.accept() threading.Thread(target=chat, args=([conn, addr])).start()
Then another user can use netcat to connect to the server and communicate. However, the program is only able to get the user’s input and send to the other side. The user from the other side is unable to send messages.
Advertisement
Answer
input()
blocks, so you are falling through your chat
function and entering the input()
loop and never checking for receiving again. Receive on the thread and enter the input loop on the main thread. TCP is full duplex so you can send/recv at the same time on two threads without turning off blocking.
I also needed to add a newline to the send()
as my netcat
was line-buffering.
import socket import threading # Bind to socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(('', 11111)) s.listen() def chat(conn, addr): while True: text = conn.recv(4096) if not text: break print("{}: {}".format(addr, text)) if __name__ == '__main__': ## Accept connections and start new thread conn, addr = s.accept() threading.Thread(target=chat, args=(conn, addr), daemon=True).start() # get user input and send message while True: msg = input(">>>") conn.sendall(msg.encode() + b'n')