I asked a question about my server to client code because I had many problems with and someone told me that the solution to the problems I had was to make a peer to peer chat which I have now done.
import socket, threading
host = "127.0.0.1"
port = 4000
s = socket.socket()
s.bind((host,port))
s.listen(5)
client_sockets = []
users = []
print("Listening")
def handle_client(conn):
while True:
try:
data = conn.recv(512)
for x in client_sockets:
try:
x.send(data)
except Exception as e:
print(e)
except:
pass
while True:
conn,addr = s.accept()
client_sockets.append(conn)
print("Connections from", addr[0], "on port",addr[1])
threading.Thread(target = handle_client,args = (conn,)).start()
import socket,threading
host = "127.0.0.1"
port = 4000
s = socket.socket()
s.connect((host,port))
def echo_data(sock):
while True:
try:
data = sock.recv(512)
print(data)
except:
pass
while True:
threading.Thread(target=echo_data,args=(s,)).start()
msg = input("Enter your message : ")
s.send(msg.encode())
The problems is that when I run the client and try talking to another client the message doesn't get sent unless the other client hits enter and also that brings me to my second problem, when the clients send messages to each other they get received in this format:
b'hi'Enter your message :
I will start with general problems not directly related to the question:
except: pass
is generally a bad idea, specially when things go wrong because it will hide potentially useful messages. It is allowed by the language but should never exist in real codein client.py you start a receiving thread per message, while you only need one for the whole client. You should start the thread outside the loop:
threading.Thread(target=echo_data,args=(s,)).start()
while True:
msg = input("Enter your message : ")
s.send(msg.encode())
Now for the questions:
the message doesn't get sent unless the other client hits enter
It can be caused by an IDE. Specifically, IDLE is known to behave poorly with multi-threaded scripts. If you correctly use one single receiving thread and starts the script from the command line (python client.py
) it should work correctly
the messages get recived in this format: b'hi'Enter your message
sock.recv(sz)
returns a byte string. You need to decode it to convert it to a Python 3 unicode string:
data = sock.recv(512)
print(data.decode())
But that is not all. It is fine for tests, but you should at least allow clients to disconnect from the server and when they do, remove them from client_sockets
. And it is common not to send back a message to the sender. So you could improve the server.py loop:
while True:
try:
data = conn.recv(512)
for x in client_sockets:
if x != conn: # do not echo to sender
x.send(data)
except Exception as e: # problem in connection: exit the loop
print(e)
break
# clear the connection
conn.close()
client_sockets.remove(conn)