I want to implement a simple two way communication between server and client using sockets. The Client sends messages and waits for replies. The Server reads messages and replies with appropriate results. I have the below codes, but both of them are hanging. Can you explain what is wrong here?
Server:
import socket
import time
HOST = "127.0.0.1"
PORT = 18735
# create socket and listen
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen()
print(f"Listening on {HOST}:{PORT}")
# accept connection
conn, addr = s.accept()
print(f"Accepted connection from {HOST}:{PORT}")
cmd = ""
while True:
data = conn.recv(2)
time.sleep(1)
if not data:
break
print(data.decode())
# conn.sendall(b"OK") This line fixes the problem!
conn.sendall(b"Finished")
s.close()
Client:
import socket
HOST = "127.0.0.1"
PORT = 18735
# create socket and connect
cs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cs.connect((HOST, PORT))
# send data
cs.sendall(b"123456")
# wait for a result
data = cs.recv(1024)
print("result: ", data)
cs.close()
EDIT: Now, I can solve the problem by sending the short message from the server. However, I wonder whether this is necessary or not?
CodePudding user response:
The server won't break out of its while
loop until the client either disconnects or at least shuts down the write half of its connection (with cs.shutdown(socket.SHUT_WR)
).
The client won't disconnect until it receives a message from the server, which the server sends outside of the while
loop (i.e. after the client disconnects/shuts down the write half of its connection).
You've created a deadlock.
Fundamentally, the issue is that it doesn't make sense to wait until the client has disconnected before you send a response to that client. Either the client needs to not expect a response back, or the server needs to send it while the client is still connected. In the case of the latter, you probably need to implement one of the following:
- The application protocol you're implementing needs a defined message structure so the server knows when the client has finished sending.
- The client needs a special sequence it can send to indicate the end of a message.
- The client needs to shut down the write half of its connection to indicate to the server that it won't send any more data.