为什么要在套接字的"recv"方法上设置保守的最大字节大小?

Why Should I Set a Conservative Max Byte Size on a Socket's 'recv' Method?

本文关键字:字节 套接字 recv 为什么 方法 设置      更新时间:2023-10-16

我正在使用Python的套接字构建一个客户端。套接字类,接收大小不等的数据(通常在500到5,000字节之间,但理论上客户端套接字可以接收500,000字节)。我还编写了将与此客户端套接字通信的服务器。

我很想知道,设置一个我确信永远不会超过的最大字节大小的风险是什么,比如:

socket.recv(1000000)

你所做的一切都是在大规模地浪费内存。

  1. 如果你以最大速度读取,你永远不会得到超过路径MTU,它通常在1500字节以下,当然是以千字节为单位测量的,而不是兆字节。

  2. 如果你没有以最大速度读取,内核中已经有一个套接字接收缓冲区,它的大小在8-64k之间,这取决于你的平台,通过TCP的操作,recv()完全不可能交付比缓冲区中更多的数据。

套接字并不像你想象的那样工作。socket.recv(N)并不意味着你会得到N个字节。这意味着您将返回最多 N个字节的。这与发送方试图向您发送多少字节无关。TCP是面向流的。这意味着您将按照发送者发送的顺序获得发送者发送给您的字节。但是你将不会得到他们在发送数据时使用的相同的"消息"边界。

必须编写代码以便能够多次调用recv,因为众所周知,socket.recv(1000000)将返回一个字节给您。现在只要你多次调用它,你不需要考虑参数的大小和你接收到的消息的大小的比较。正如其他发帖者所说,你希望传递的值与堆栈其他级别上最大缓冲区的大小相当。其中一个缓冲区(路径MTU)可能在1500左右(但它可以更大或更小)。但是内核的TCP/IP堆栈中的本地接收缓冲区更大,可能在64k或128k左右。这些可能接近合理的使用值。

但是,我建议不要在这个级别编写网络代码。已经有人这么做了——或多或少是死的。您可能会更好地关注应用程序的新部分,并重用一些为您处理这些细节的现有库。我推荐Twisted.