Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python TCP服务器接收拆分为多个数据包的单个TCP数据包_Python_Sockets_Tcp - Fatal编程技术网

Python TCP服务器接收拆分为多个数据包的单个TCP数据包

Python TCP服务器接收拆分为多个数据包的单个TCP数据包,python,sockets,tcp,Python,Sockets,Tcp,在我托管的基于Python的TCP服务器上,我很难确定某些数据包分裂问题的原因 我的客户端连接到服务器后,会向服务器发送一个字符串,后跟/n 数据包的Wireshark预览如下所示: 在本例中,您可以看到有效负载是“作为特别的英国婴儿土豆/n” 我的TCP服务器具有以下接收代码: def listenToClient(self、client、address): 大小=1024 尽管如此: 尝试: #从客户端接收数据 数据=client.recv(大小) 打印('已接收客户端数据',客户端) 打

在我托管的基于Python的TCP服务器上,我很难确定某些数据包分裂问题的原因

我的客户端连接到服务器后,会向服务器发送一个字符串,后跟
/n

数据包的Wireshark预览如下所示:

在本例中,您可以看到有效负载是“作为特别的英国婴儿土豆/n”

我的TCP服务器具有以下接收代码:

def listenToClient(self、client、address):
大小=1024
尽管如此:
尝试:
#从客户端接收数据
数据=client.recv(大小)
打印('已接收客户端数据',客户端)
打印(datetime.now())
打印(“收到的原始数据:”,data.hex())
数据:作为额外数据
除ConnectionAbortedError外:
打印(datetime.now())
打印('客户端已断开连接:',客户端)
client.close()
返回错误
当收到上述数据包时,它将打印以下内容:

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
接收到客户端数据
2020-11-14 22:48:20.087507
收到的原始数据:61732074685206578747261
数据:作为额外数据
收到的客户数据
2020-11-14 22:48:20.092495
收到的原始数据:207370656369616c2062726974697368206261627920706f7461
资料来源:英国特殊婴儿波塔
收到的客户数据
收到的原始数据:746f65730a0a
2020-11-14 22:48:20.117488
数据:脚趾
不知何故,这个TCP数据包被分成了3个较小的数据包


你知道这是怎么发生的吗?

TCP不是一个基于消息的协议,而是一个字节流。单个
发送
并不意味着所有内容都将在单个TCP数据包内发送。同样,不能指望单个
recv
与单个
send
匹配


如果需要消息语义,则需要在字节流的顶部添加这些语义。通常,这是通过显式长度指示器、特殊分隔符或只有一条消息来完成的,即关闭连接将结束消息。然后需要多次调用recv,直到得到完整的消息。

TCP不是基于消息的协议,而是字节流。单个
发送
并不意味着所有内容都将在单个TCP数据包内发送。同样,不能指望单个
recv
与单个
send
匹配


如果需要消息语义,则需要在字节流的顶部添加这些语义。通常,这是通过显式长度指示器、特殊分隔符或只有一条消息来完成的,即关闭连接将结束消息。然后您需要多次调用
recv
,直到收到完整的消息。

根据下面的说明,您可以如何构造代码以接收整个消息:

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

根据此处的说明,您可以如何构造代码以接收整个消息:

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

请看我在这里的评论。。。请看我在这里的评论。。。谢谢你的及时答复。在本例中,我的“特殊分隔符”是附加在每个句子末尾的
\n
。是否有一种方法可以使recv阻塞并继续连接接收到的流,直到它遇到此
\n
?我不想关闭连接,因为为此我需要一个长寿命的TCP连接:)@OscarVanL:
recv
在出现特定字符之前无法只读。您需要自己实现这一点。请参阅示例,了解有关如何操作的一些想法。谢谢,这看起来很完美。我会试试:)我通过修改这个答案使它起作用了,谢谢!谢谢你的及时答复。在本例中,我的“特殊分隔符”是附加在每个句子末尾的
\n
。是否有一种方法可以使recv阻塞并继续连接接收到的流,直到它遇到此
\n
?我不想关闭连接,因为为此我需要一个长寿命的TCP连接:)@OscarVanL:
recv
在出现特定字符之前无法只读。您需要自己实现这一点。请参阅示例,了解有关如何操作的一些想法。谢谢,这看起来很完美。我会试试:)我通过修改这个答案使它起作用了,谢谢!不能保证字节流不会在UTF-8多字节字符的中间被分割,所以你不应该解码它直到你确定有一个完整的消息。此代码还假设您一直在接收,直到套接字关闭为止,因此只能接收一条消息。@MarkTolonen关于我代码中的解码部分,您完全正确。另一方面,关于你评论的第二部分,这个问题涉及一个TCP数据包,所以只有一条消息,除非我错了。我提到发送一条消息后加上一个\n,之后不一定要关闭套接字。它确实需要一个缓冲层,从流中填充缓冲区,直到看到换行符,然后将缓冲区的部分返回到并包括换行符。此后,缓冲区中剩余的任何内容将是下一条消息的一部分。不能保证字节流不会在UTF-8多字节字符的中间被分割,所以在确定完整消息之前,不应该对其进行解码。此代码还假设您一直在接收,直到套接字关闭为止,因此只能接收一条消息。@MarkTolonen关于我代码中的解码部分,您完全正确。另一方面,关于你评论的第二部分,这个问题涉及一个TCP数据包,所以只有一条消息,除非我错了。我提到发送一条消息后加上一个\n,之后不一定要关闭套接字。它确实需要一个缓冲层,从流中填充缓冲区,直到看到换行符,然后返回部分