我正在使用 Python 的 socket.socket 类构建一个客户端,该类接收大小不同的数据(通常在 500 到 5,000 字节之间,但理论上客户端套接字可以接收 500,000 字节)。我还在编写将与此客户端套接字通信的服务器。
我很想知道,设置我可以确信我永远不会超过的最大字节大小的风险是什么,例如:
socket.recv(1000000)
即使我知道这远远大于套接字实际使用量的 99%。
我正在使用 Python 的 socket.socket 类构建一个客户端,该类接收大小不同的数据(通常在 500 到 5,000 字节之间,但理论上客户端套接字可以接收 500,000 字节)。我还在编写将与此客户端套接字通信的服务器。
我很想知道,设置我可以确信我永远不会超过的最大字节大小的风险是什么,例如:
socket.recv(1000000)
即使我知道这远远大于套接字实际使用量的 99%。
你所做的只是以史诗般的规模浪费内存。
如果您以最大速度阅读,您将永远不会超过路径 MTU,它通常小于 1500 字节,并且肯定以千字节而不是兆字节为单位。
如果您没有以最大速度阅读,内核内部已经有一个套接字接收缓冲区,根据您的平台,其大小在 8-64k 范围内,并且通过 TCP 的操作,recv() 完全不可能提供比该缓冲区中更多的数据。
套接字不像你想象的那样工作。 socket.recv(N)
并不意味着你会得到 N 个字节。这意味着您最多将返回N 个字节。这与发件人尝试发送给您的字节数无关。TCP 是面向流的。这意味着您将按照发送者发送它们的顺序获得发送者发送给您的字节。但是你不会得到他们在发送数据时使用的相同的“消息”边界。
您必须编写代码才能多次调用 recv,因为据您所知,socket.recv(1000000)
它将返回一个字节给您。现在,只要您多次调用它,您就不必考虑参数的大小与您收到的消息的大小相比。正如其他海报所说,您希望传递一个与堆栈其他级别的最大缓冲区大小相当的值。其中一个缓冲区(路径 MTU)可能约为 1500(但它可以更大或更小)。但是内核的 TCP/IP 堆栈中的本地接收缓冲区更大,可能在 64k 或 128k 左右。这些可能接近使用的合理值。
不过,我建议不要在这个级别实际编写网络代码。它已经完成了 - 或多或少地死亡。专注于应用程序的新颖部分并重新使用一些为您处理这些细节的现有库可能会好得多。我推荐Twisted。