零字节接收:目的说明

Zero byte receives: purpose clarification

我正在学习使用 IO 完成端口进行服务器开发。我的书 "Network Programming for Microsoft Windows - Second Edition" 陈述如下:

With every overlapped send or receive operation, it is probable that the data buffers submitted will be locked. When memory is locked, it cannot be paged out of physical memory. The operating system imposes a limit on the amount of memory that may be locked. When this limit is reached, overlapped operations will fail with the WSAENOBUFS error. If a server posts many overlapped receives on each connection, this limit will be reached as the number of connections grow. If a server anticipates handling a very high number of concurrent clients, the server can post a single zero byte receive on each connection. Because there is no buffer associated with the receive operation, no memory needs to be locked. With this approach, the per-socket receive buffer should be left intact because once the zero-byte receive operation completes, the server can simply perform a non-blocking receive to retrieve all the data buffered in the socket's receive buffer. There is no more data pending when the non-blocking receive fails with WSAEWOULDBLOCK.

现在,我正在努力理解这一段;我想我知道了 ,但我想确认一下

我了解如果我 post 使用大缓冲区进行多次 WSARecv() 调用,内存将被锁定。但我不完全确定零字节缓冲区如何防止这种情况。

我想是这个(请确认):

如果我有 n 个连接,并且我 post 50 WSARecv() 个调用在每个连接上使用 1KB 缓冲区,即锁定的总内存 n * 50KB。所有这些内存都被锁定,无论它是否实际被使用(即是否有任何内容从 TCP 缓冲区复制到其中)。因此,如果我继续添加更多连接,我将继续锁定更多可能或可能永远被使用的内存。因此我可以 运行 出来,但有 WSAENOBUFS 错误。

但是,如果我 post 在每个连接上接收到一个零字节,将在该连接上生成一个完成数据包 仅当有数据可供读取时 (这是我的第一个假设,对吗?)

现在,当我知道有一些数据时,我可以 post 一个 WSARecv() 缓冲区为 1KB(或多少)——或者确实循环重复读取它我的书 - 知道它会立即被填满 因此不会一直闲置和锁定 (第二个假设,正确吗?)

问题 1 因此,如果我的两个假设是正确的,那么我已经理解了我的书 :) 这意味着理论上我的服务器可以 post 在建立新连接时接收零字节,然后在完成数据包时生成,读取所有数据直到没有更多数据,然后 post 接收另一个零字节 - 正确吗?

问题 2 但是,如果我收到 lots 的零字节的完成数据包是否仍然存在这样的风险,即一次 posts ,然后我继续进行 multiple WSARecv() 调用,我仍然会以 WSAENOBUFS?

失败告终

希望有人能为我澄清这两个假设和两个问题。

好的,我已经对此进行了研究并进行了实验,并发现了以下内容:

假设:

1)假设1是正确的。 2) 我认为假设 2 是正确的。

问题

1) 我已经测试过了,这似乎有效。 2) 我想这仍然是一种可能性,但比我用 none-零缓冲区发布接收的可能性要小得多。

请注意,当发送速度过快时,我们仍然会引发 WSAENOBUF 错误;更多详情 here.