2

I have the following case:

SERVER

sock = socket.socket()
sock.bind((hostaddr, port))
sock.listen(backlog)
print(f'Server listenning on {hostaddr}:{port}')

while True:
    client_sock, client_address = self.sock.accept()
    print(f'Incoming connection from {client_address[0]}:{client_address[1]}')

    while True:
        data = client_socket.recv(buffer_size)
        if not data:
           break

        print(f'Received "{data.decode()}" from {client_address[0]}:{client_address[1]}')    

        reply = f'Server: I got the message "{data.decode()}"'.encode()
        client_socket.sendall(reply)

    client_socket.close()

CLIENT

sock = socket.socket()
sock.connect(server_address)
sock.sendall('Lorem Ipsum'.encode())

while True:
    data = sock.recv(buffer_size)
    if not data:
        break
    print(data.decode())

sock.close()

I first start the server, then I start the client, and I get the following logs:

SERVER

Server listening on 172.16.0.110:8081
Incoming connection from 172.16.0.110:62388
Received "Lorem Ipsum" from 172.16.0.110:62388

CLIENT

Server reply: I got the message "Lorem Ipsum"

I wanted to get the server reply and then the client should finish, but both server and client enter an infinite loop and keep running forever. Why and how to fix that? I'm using Python 3.6.0 on Windows 10 x64 in an IPv4 network.

7
  • Remove the loops? Commented Sep 2, 2017 at 22:59
  • But the loop in the server needs to be there to keep accepting connections, and the loop in the client needs to be there to get all the data in chunks of buffer_size Commented Sep 2, 2017 at 23:04
  • In the server, the loop has nothing to do with accepting connections. You don't need a loop to accept data, if the data fits into the buffer, it'll be done in one call. Commented Sep 2, 2017 at 23:07
  • So, I removed both loops from my server code, now the client gets the response, but both server and client finishes with error code 0, when in reality I just wanted the client to finish. I don't want my server finishing with just one call, it needs to stay alive forever. Also, every server-client socket example out there uses loop to keep the server always running. I really didn't get why you said to remove it. Commented Sep 2, 2017 at 23:14
  • I meant the loops that were looping over the .recv call. Commented Sep 2, 2017 at 23:18

2 Answers 2

3

You must define a protocol, which is just the rules for how messages are exchanged and formatted, and how message boundaries are communicated. It appears you simply want the client to send some data and read the server response. You can achieve this by closing the write half of the client connection, in your case by calling sock.shutdown(socket.SHUT_WR), after the sock.sendall(...).

On the server side this is the read half of the same connection, and the servers detects this as EOF, causing socket.recv() to return a zero-length bytes object.

For more complicated protocols for which you want to send multiple messages on the same connection, a different strategy must be used. One simple example for a binary protocol would be to send 4 bytes representing the length in bytes of the message, then send that many bytes for the subsequent message itself.

Sign up to request clarification or add additional context in comments.

1 Comment

Amazing, thanks. I changed the title of the question trying to make it more search-friendly, as this might be useful for people in there future.
1

One way is to set a timeout for the socket so it doesn't block forever when waiting for reply using socket.settimeout() as the following:

sock = socket.socket()
sock.connect(server_address)
sock.sendall('Lorem Ipsum'.encode())
sock.settimeout(5.0) # sets timeout to 5 seconds

while True:
    data = sock.recv(buffer_size)
    if not data:
        break
    print(data.decode())

sock.close()

1 Comment

Thanks, this also works, but JamesKPolk answer was more fit for my case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.