因为我不是以英语为母语的人,所以我可能会错过一些东西,所以也许这里有人比我更了解。
取自WSASendMSDN 上的文档:
lpBuffers [输入]
指向 WSABUF 数组的指针
结构。每个WSABUF结构
包含一个指向缓冲区的指针和
缓冲区的长度(以字节为单位)。为一个
Winsock应用程序,一旦WSASend
函数被调用,系统拥有
这些缓冲区和应用程序可能
不访问它们。该数组必须
在有效期内保持有效
发送操作。
好的,你能看到粗体文字吗?这就是不明白的地方!
我可以想到这句话的两种翻译(可能是别的东西,你能想到的):
翻译 1 -“缓冲区”指的是重叠结构我在调用它时传递了这个函数。仅当收到有关该对象的完成通知时,我才可以再次重用该对象。
翻译 2 -“缓冲区”指的是实际缓冲区,那些包含我要发送的数据的人。如果 WSABUF 对象指向一个缓冲区,那么在操作完成之前我无法触及该缓冲区。
谁能告诉这句话的正确解释是什么?
还有......如果答案是第二个——你会如何解决它?
因为对我来说,这意味着对于我发送的每个数据/缓冲区,我必须在发送方保留它的副本 - 因此在高流量应用程序上有许多“待处理”缓冲区(不同大小),这确实会发生损害“可扩展性”。
声明一:
除了上面的段落(“和...”)之外,我认为 IOCP 会将要发送的数据复制到它自己的缓冲区并从那里发送,除非您设置SO_SNDBUF为零。
声明2:
我使用堆栈分配的缓冲区(你知道,类似char cBuff[1024];
在函数体中 - 如果对主要问题的翻译是第二个选项(即缓冲区必须保持原样,直到发送完成),那么......这真的把事情搞砸了!你能想个办法解决吗? (我知道,我在上面换句话说)。
答案是,在操作完成之前,重叠结构和数据缓冲区本身无法重用或释放。
这是因为操作是异步完成的,因此即使数据最终被复制到 TCP/IP 堆栈中操作系统拥有的缓冲区中,也可能要等到将来某个时间才会发生,并且您会收到写入完成发生的通知。请注意,如果您在没有显式流量控制的情况下发送并依赖 TCP 堆栈为您进行流量控制,则在写入完成时,这些可能会延迟令人惊讶的时间(请参见此处:使用 WSASend 的一些重叠未使用 GetQueuedCompletionStatus 及时返回?) ...
您不能使用堆栈分配的缓冲区,除非您将事件放置在重叠结构中并阻止它直到异步操作完成;这样做没有多大意义,因为你会比正常的阻塞调用增加复杂性,并且通过发出异步调用然后等待它也不会获得很多好处。
在我的 IOCP 服务器框架中(您可以从here)我使用动态分配的缓冲区,其中包括重叠结构并且是引用计数的。这意味着当完成发生并且引用被释放时,就会发生清理(在我的例子中,它们被返回到池中以供重用)。这也意味着您可以选择在操作后继续使用缓冲区,并且清理仍然简单。
另请参阅此处:I/O 完成端口,如何释放每个套接字上下文和每个 I/O 上下文?
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)