我应该同时进行 WSASend() 调用吗?
Posted
技术标签:
【中文标题】我应该同时进行 WSASend() 调用吗?【英文标题】:Should I make simultaneous WSASend() calls? 【发布时间】:2015-03-05 11:28:32 【问题描述】:我知道为了同时调用WSASend()
,我需要为每个调用提供一个唯一的WSAOVERLAPPED
和WSABUF
实例。但这意味着我必须为每次调用跟踪这些实例,这会使事情变得复杂。
我认为,如果我创建一个线程来不是同时调用,而是顺序调用,那将是一个更好的主意。该线程将等待一个队列,该队列将持有WSASend()
请求(每个请求将包含套接字句柄和我要发送的字符串)。当我最终调用WSASend()
时,我将阻塞线程,直到我收到来自等待完成端口的线程的唤醒信号,告诉我WSASend()
已经完成,然后我继续获取下一个请求。
如果这是个好主意,那么我应该如何实现队列以及如何对其进行阻塞提取调用(而不是使用轮询)?
【问题讨论】:
第一个问题是对等方是否能够理解所有这些并发发送。真的可以吗? @EJP 是的,每个WSASend()
调用都会发送一条定义长度且彼此不相关的消息。
听起来你应该对我使用阻塞 I/O,并使用互斥锁对其进行序列化。比你在这里提出的要简单得多。
@EJP 但是我想处理成千上万的客户端,所以阻塞 I/O 是行不通的。
如果你打算使用发送者线程,你可以在排队/出队时使用同步机制来锁定队列。应该够了。
【参考方案1】:
WSABUF
可以基于堆栈,因为WSASend()
负责在返回之前复制它。 OVERLAPPED
和数据缓冲区本身必须存在,直到提取和处理操作的 IOCP 完成。
我一直使用“扩展”OVERLAPPED
结构,它包含数据缓冲区、重叠结构和WSABUF
。然后,我使用引用计数系统来确保“每个操作数据”一直存在,直到没有人需要它为止(也就是说,我在 API 调用启动操作之前获取引用,并在删除操作完成后释放引用从 IOCP 完成 - 请注意,这里的引用不是 100% 必需的,但它们可以更容易地将生成的数据缓冲区传递给代码的其他部分)。
对于 TCP 连接来说,在任何时候传输数据的 TCP“窗口大小”并有更多的待处理数据是最优化的,这样窗口总是保持满,并且总是以最大发送连接可以采取。要通过重叠 I/O 实现这一点,通常最好有许多 WSASend()
调用待处理。但是,您不希望有太多待处理(请参阅here),实现这一点的最简单方法是跟踪您待处理的字节数、队列字节以供以后传输并在存在时从传输队列发送发送完成...
【讨论】:
以上是关于我应该同时进行 WSASend() 调用吗?的主要内容,如果未能解决你的问题,请参考以下文章
我应该为 WSASend 和 WSARecv 使用不同的 WSAOVERLAPPED 结构吗?
WSASend() 和 WSARecv() 的所有错误代码是不是意味着套接字已断开连接?
具有多个缓冲区的 WSASend() - 可以完成不完整吗?