0
votes

I'm having some trouble identifying the cause of some packet splitting issues on a Python-based TCP server I am hosting.

After my client has connected to the server, it sends a string to the server, followed by /n.

A Wireshark preview of a packet can be seen below: enter image description here

In this case, you can see the payload is "as the extra special british baby potatoes/n"

My TCP Server has the following receiving code:

    def listenToClient(self, client, address):
        size = 1024
        while True:
            try:
                # Receive data from the client
                data = client.recv(size)
                print('CLIENT Data Received', client)
                print(datetime.now())
                print("Raw data received: ", data.hex())
                Data: as the extra
            except ConnectionAbortedError:
                print(datetime.now())
                print('CLIENT Disconnected:', client)
                client.close()
                return False

When receiving the above packet, it prints the following:

CLIENT Data Received <socket.socket fd=428, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.0.16', 12345), raddr=('192.168.0.14', 47234)>
2020-11-14 22:48:20.087507
Raw data received:  617320746865206578747261
Data: as the extra

CLIENT Data Received <socket.socket fd=428, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.0.16', 12345), raddr=('192.168.0.14', 47234)>
2020-11-14 22:48:20.092495
Raw data received:  207370656369616c2062726974697368206261627920706f7461
Data:  special british baby pota

CLIENT Data Received <socket.socket fd=428, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.0.16', 12345), raddr=('192.168.0.14', 47234)>
Raw data received:  746f65730a0a
2020-11-14 22:48:20.117488
Data: toes

Somehow, this single TCP packet has been split into 3 smaller packets.

Do you know how this may have happened?

2
Please see my comment here... stackoverflow.com/q/64790051/2836621 - Mark Setchell

2 Answers

2
votes

TCP is not a message based protocol but a byte stream. A single send does not mean that everything will be sent inside a single TCP packet. Similarly it cannot be counted on that a single recv will match a single send.

If you want message semantics you need to add these on top of the byte stream. Typically this is done with an explicit length indicator, a special separator or by having only a single message, i.e. close of connection will end the message. And then you need to call recv multiple times until you got the full message.

0
votes

In accordance with the explanation of Steffen Ullrich here is how you can structure your code to receive the whole message:

def listenToClient(self, client, address):
        size = 1024
        while True:
            try:
                # Receive data from the client
                data = ''
                while True:
                     r = client.recv(size)
                     if not r:
                         break
                     data += r
                print('CLIENT Data Received', client)
                print(datetime.now())
                print("Raw data received: ", data.hex())
                Data: as the extra
            except ConnectionAbortedError:
                print(datetime.now())
                print('CLIENT Disconnected:', client)
                client.close()
                return False