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:
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?
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, ie close of connection will end the message. And then you need to call recv
multiple times until you got the full message.
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.