When keeping a client socket open to send several messages, why does the program give an error when there is a big delay in messages?

后端 未结 2 1730
后悔当初
后悔当初 2020-12-22 13:16

There is a server that listens to connections. The client socket connects to the server and calls sendall() several times in a loop before closing it. However,

相关标签:
2条回答
  • 2020-12-22 14:05

    Your server reads exactly once from the client and receives up to 72 bytes then closes the connection. If the client can send all 10 messages fast enough it won't get an error. Read about the Nagle Algorithm which:

    inhibit[s] the sending of new TCP segments when new outgoing data arrives from the user if any previously transmitted data on the connection remains unacknowledged.

    Your server will never receive all the messages (total 91 bytes) but the client won't error if it gets them all sent.

    A small change to the server makes sure it receives all the data (no matter the delay) by waiting until the client closes the connection:

    with connection:
        while True:
            data = connection.recv(72)
            if not data: break # empty data means client closed connection.
            print('Client says "{}"'.format(data))
    

    This still won't receive messages one-by-one. TCP is a streaming protocol so the messages get concatenated together. You need to add buffering and a means to extract only complete messages from it. Example (Python 3.6+):

    client.py

    import socket
    
    host = '127.0.0.1'
    port = 65432
    
    with socket.socket() as s:
        s.connect((host, port))
        for i in range(10):
            # Use newline as message delimiter.
            s.sendall(f'message {i+1}\n'.encode())
    

    server.py

    import socket
    
    with socket.socket() as s:
        s.bind(('127.0.0.1', 65432))
        s.listen()
    
        while True:
            connection, address = s.accept()
    
            with connection:
                data = b''
                while True:
                    chunk = connection.recv(16)
                    if not chunk: break # client closed connection
                    data += chunk # buffer input
                    while b'\n' in data: # break off messages and display
                        msg,_,data = data.partition(b'\n')
                        print(f'Client says "{msg.decode()}"')
                if data:
                    print(f'Incomplete message: {data}')
    

    Output:

    Client says "message 1"
    Client says "message 2"
    Client says "message 3"
    Client says "message 4"
    Client says "message 5"
    Client says "message 6"
    Client says "message 7"
    Client says "message 8"
    Client says "message 9"
    Client says "message 10"
    
    0 讨论(0)
  • 2020-12-22 14:16

    Your server code is incorrect. You should use threading or any other technique to serve multiple client connections. What is happening here:

    1) Server accepts first socket

    2) Server receives 72 bytes

    3) Connection is closed because with operator closes it

    4) Server goes to next accept-loop

    0 讨论(0)
提交回复
热议问题