我可以反复调用 WSASend() 吗?

Posted

技术标签:

【中文标题】我可以反复调用 WSASend() 吗?【英文标题】:Can I call WSASend() repeatedly? 【发布时间】:2015-02-23 12:31:32 【问题描述】:

在使用 IOCP 时,如果我拨打 WSASend(),我是否必须等待通知到达才能再次拨打电话,或者我可以在收到任何通知之前多次拨打它,例如允许这样的事情:

WSASend();

// Call it again without waiting for notification of previous call
WSASend();

// Call it again without waiting for notification of previous call
WSASend();

【问题讨论】:

【参考方案1】:

是的,您可以发出多个 I/O 请求而无需等待完成通知。或者,您可以一次调用 WSASend() 多个缓冲区。

无论哪种方式,或两者兼而有之,都可以正常工作。每个调用的 OVERLAPPED 块本质上是指向 I/O 请求的链表的指针,因此当 I/O 资源可用时,它们都可以被内核和通信堆栈排队并执行。

这也适用于 WSARecv 等重叠 I/O。这允许内核/堆栈在用户线程代码处理之前通知的缓冲区时加载缓冲区。

注意:OVERLAPPED 块和缓冲区在每次调用时都必须是唯一的,并且它们的生命周期必须延长到完成通知。在用户线程处理完成通知之前,您不能让它们被 RAII 或删除。缓冲区和 OVERLAPPED 通常是一个“IOrequest”类的成员(使用“SocketContext*”类指针成员将每个 IOrequest 与其绑定的套接字连接起来)。

【讨论】:

【参考方案2】:

是的,您可以在单个套接字上发出多个重叠操作,而无需等待任何完成。

在 TCP 套接字上进行多个未完成的 WSASend() 调用时需要注意的一件事是,您正在有效地将 WSASend() 调用中使用的缓冲区的资源管理移交给另一端的对等方。插座。这样做的原因是,如果您发送数据而对等方读取数据的速度不如您发送的那么快,那么您最终将导致 TCP 的流量控制启动。这不会阻止您发出更多的 WSASend() 调用和所有你会注意到完成需要越来越长的时间。有关详细信息,请参阅here。

【讨论】:

以上是关于我可以反复调用 WSASend() 吗?的主要内容,如果未能解决你的问题,请参考以下文章

具有多个缓冲区的 WSASend() - 可以完成不完整吗?

在迂回的 WSASend 中阻塞数据包

我应该为 WSASend 和 WSARecv 使用不同的 WSAOVERLAPPED 结构吗?

我应该处理 WSASend() 可能不会发送所有数据的事实吗?

是否有可能不会收到 WSASend 调用的完成?

如何避免使用函数调用 WSAsend 将多个缓冲区组合成一个 UDP 数据包?