3

由于我不是以英语为母语的人,我可能会遗漏一些东西,所以也许这里有人比我更了解。

取自WSASend在 MSDN 的文档:

lpBuffers [输入]

指向 WSABUF 结构数组的指针。每个 WSABUF 结构都包含一个指向缓冲区的指针和缓冲区的长度(以字节为单位)。对于 Winsock 应用程序,一旦调用 WSASend 函数,系统就拥有这些缓冲区,应用程序可能无法访问它们。该数组必须在发送操作期间保持有效。

好的,你能看到粗体字吗?那是不清楚的地方!

我可以想到这行的两种翻译(可能是别的东西,你可以命名它):
翻译 1 - “缓冲区”指的是我在调用此函数时传递的 OVERLAPPED 结构。只有在收到有关它的完成通知时,我才能再次重用该对象。
翻译 2 - “缓冲区”指的是实际的缓冲区,即那些包含我正在发送的数据的缓冲区。如果 WSABUF 对象指向一个缓冲区,那么在操作完成之前我不能触摸这个缓冲区。

谁能告诉那条线的正确解释是什么?

而且.....如果答案是第二个-您将如何解决?
因为对我来说,这意味着对于我发送的每个数据/缓冲区,我必须在发送方保留一份副本 - 因此在高流量应用程序上有许多“待处理”缓冲区(不同大小),这真的会伤害“可扩展性”。

声明 1:
除了上述段落(“And....”)之外,我认为 IOCP 会将要发送的数据复制到它自己的缓冲区并从那里发送,除非您将SO_SNDBUF设置为零。

声明 2:
我使用堆栈分配的缓冲区(你知道,类似于char cBuff[1024];函数体的内容 - 如果主要问题的转换是第二个选项(即缓冲区必须保持原样,直到发送完成),那么......这真的把事情搞砸了!你能想出办法解决它吗?(我知道,我在上面换句话说)。

4

1 回答 1

4

答案是重叠结构和数据缓冲区本身在操作完成之前不能被重用或释放。

这是因为操作是异步完成的,因此即使数据最终被复制到 TCP/IP 堆栈中操作系统拥有的缓冲区中,这可能要到将来的某个时间才会发生,并且您会在写入完成时收到通知。请注意,如果您在没有显式流量控制的情况下发送并依靠 TCP 堆栈为您进行流量控制,则写入完成可能会延迟惊人的时间(请参阅此处:使用 WSASend 的一些重叠未及时返回使用 GetQueuedCompletionStatus 的方式?)...

您不能使用堆栈分配的缓冲区,除非您在重叠结构中放置一个事件并阻塞它,直到异步操作完成;这样做并没有多大意义,因为您在正常阻塞调用上增加了复杂性,并且通过发出异步调用然后等待它不会获得很多好处。

在我的 IOCP 服务器框架(您可以从这里免费获得)中,我使用动态分配的缓冲区,其中包括 OVERLAPPED 结构并且是引用计数的。这意味着清理(在我的情况下,它们被返回到池中以供重用)在完成发生并释放引用时发生。这也意味着您可以选择在操作后继续使用缓冲区并且清理仍然简单。

另请参阅:I/O 完成端口,如何释放每个套接字上下文和每个 I/O 上下文?

于 2010-06-13T10:47:58.657 回答