我在 IOCP 服务器上工作(重叠 I/O,4 线程,CreateIoCompletionPort
, GetQueuedCompletionStatus
, WSASend
ETC)。我还创建了一个自动重置事件,并将每个异步 I/O 操作的句柄放入 OVERLAPPED 结构中。
问题是:如何正确向所有连接的套接字发送缓冲区?每个套接字都存储在上下文信息结构的链表中。
我不确定下面的方法是否可以?
...
DWORD WINAPI WorkerThread() { // 1 of 4 workthread
...
GetQueuedCompletionStatus(...);
...
PPER_SOCKET_CONTEXT pTmp1, pTmp2;
pTmp1 = g_pCtxtList; // start of linked list with sockets
EnterCriticalSection(&g_CriticalSection);
while( pTmp1 )
{
pTmp2 = pTmp1->pCtxtBack;
WaitForSingleObject(pTmp1->pIOContext->Overlapped.hEvent,infinite);
// if there is any pending wsasend on this socket,wait to completed, so
// we can post another wsasend using the same overlapped structure
// and buffer
WSASend(pTmp1->Socket,...,&(pTmp1->pIOContext->Overlapped), NULL);
pTmp1 = pTmp2;
}
LeaveCriticalSection(&g_CriticalSection);
...
}
如果另一个线程也尝试同时执行相同的工作,会发生什么情况?
在所有线程中使用 GQCS 和等待函数是个好主意吗?
任何有关的线索wsasends
对于多线程 iocp 服务器中的所有客户端,我们将不胜感激。
thx
不确定我是否理解其中的一些内容。 IOCP 通常不使用 OVL 结构中的 hEvent 字段。 I/O 完成是通过将完成消息排队到“完成端口”(即队列)来发出信号的。您似乎正在使用 hEvent 字段来发送一些“不寻常”的额外信号来管理单个发送数据缓冲区和 OVL 块。
显然,我没有从你的帖子中了解整个故事,但在我看来,你在 tx 方面为自己做了繁重的工作,并且序列化发送会扼杀性能:)
您是否必须使用相同的 OVL/缓冲区对象来连续发送?我通常做的是为每次发送使用不同的 OVL/缓冲区,然后立即将其排队。内核将按顺序发送缓冲区并为每个缓冲区返回一条完成消息。一个套接字上的多个 IOCP tx 请求没有问题 - 这就是 OVL 块的用途 - 将它们在内核堆栈内链接在一起。
让多个 IOCP 接收对未完成的套接字的请求存在一个问题 - 可能会发生两个池线程同时获取同一套接字的完成数据包,因此可能导致无序处理。 “正确”修复该问题需要在每个发出的 rx 缓冲区/OVL 对象中增加序列号,并在每个套接字对象中使用临界区和缓冲区列表来“保存”无序缓冲区,直到所有较早的缓冲区都被删除。已经处理过的。我怀疑许多 IOCP 服务器只是通过一次只接收一个 rx IOCP 请求来避免这个问题(可能会以牺牲性能为代价)。
如果不断地构建和销毁缓冲区,以这种方式获取大量缓冲区可能会有点费力,所以我通常不会打扰,只是在启动时创建几千个缓冲区并推送它们,(好吧,指向它们的指针) ,到生产者-消费者“池队列”上,当需要 tx 或 rx 时将它们弹出并再次将它们推回。对于 tx,当 IOCP 池线程之一拾取发送完成消息时,就会发生这种情况。在 rx 的情况下,当池线程(或池线程已将对象排队到其中的某个其他线程)已处理该对象并且不再需要它时,就会发生这种情况。
啊..您想将完全相同的内容发送到套接字列表 - 就像聊天服务器类型的东西。
好的。那么一个缓冲区和多个 OVL 块怎么样?我没有尝试过,但不明白为什么它不起作用。在单个缓冲区对象中,保留您在“发送到所有客户端”循环中发送的重叠发送请求数量的原子引用计数。当您将缓冲区放回到完成数据包中时,将 refCount 减少到零,并在减至 0 时删除/重新池化缓冲区。
我认为这应该可行,(?)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)