Multithreading WSAsend到多线程iocp服务器中所有连接的套接字
我在IOCP服务器上工作(重叠I/O,4个线程,Multithreading WSAsend到多线程iocp服务器中所有连接的套接字,multithreading,sockets,iocp,Multithreading,Sockets,Iocp,我在IOCP服务器上工作(重叠I/O,4个线程,CreateIoCompletionPort,GetQueuedCompletionStatus,WSASend等)。我还为每个异步I/O操作创建了一个自动重置事件,并将句柄放在重叠结构中 问题是:如何正确地将缓冲区发送到所有连接的套接字?每个套接字都存储在上下文信息结构的链接列表中 我不确定下面的方法是否可行 ... DWORD WINAPI WorkerThread() { // 1 of 4 workthread ... GetQueuedC
CreateIoCompletionPort
,GetQueuedCompletionStatus
,WSASend
等)。我还为每个异步I/O操作创建了一个自动重置事件,并将句柄放在重叠结构中
问题是:如何正确地将缓冲区发送到所有连接的套接字?每个套接字都存储在上下文信息结构的链接列表中
我不确定下面的方法是否可行
...
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和waits函数是个好主意吗?
如果您对多线程iocp服务器中的所有客户端提供有关wsasends的任何线索,我们将不胜感激。
thx我不确定我是否理解其中的一些内容。IOCP通常不在OVL结构中使用hEvent字段。I/O完成通过将完成消息排入“完成端口”(即队列)来发出信号。您似乎正在使用hEvent字段来管理单个发送数据缓冲区和OVL块,以获得一些“不寻常”的额外信号 显然,我不知道你文章的全部内容,但在我看来,你在tx端为自己做了大量工作,发送的连续性将扼杀性能:) 成功发送时是否必须使用相同的OVL/buffer对象?我通常做的是为每次发送使用不同的OVL/缓冲区,并立即将其排队。内核将按顺序发送缓冲区,并为每个缓冲区返回一条完成消息。套接字上的多个IOCP tx请求(这就是OVL块的用途)在内核堆栈中将它们链接在一起是没有问题的 让多个IOCP接收针对未完成套接字的请求存在一个问题—两个池线程可能同时获取同一套接字的完成数据包,因此可能导致处理顺序混乱。要“正确”修复该问题,需要在发出的每个rx buffer/OVL对象中增加序列号,并在每个套接字对象中“保存”无序缓冲区,直到处理完所有较早的缓冲区。我怀疑许多IOCP服务器只是通过一次只接收一个rx IOCP请求来回避这个问题(可能以牺牲性能为代价) 如果缓冲区被不断地构造和破坏,那么以这种方式通过大量缓冲区可能会有点费力,所以我通常不会在启动时创建几千个缓冲区,并将它们(好的,指向它们的指针)推到生产者-消费者的“池队列”上,当需要发送或接收时,将其弹出,然后将其重新打开。在发送的情况下,当一个IOCP池线程拾取发送完成消息时,就会发生这种情况。在rx的情况下,当池线程(或池线程已将对象排入队列的其他线程)已对其进行处理且不再需要它时,就会发生这种情况 啊。。您希望向套接字列表发送完全相同的内容,就像聊天服务器类型的东西一样 嗯。那么一个缓冲区和多个OVL块呢?我没有试过,但不明白为什么它不起作用。在单缓冲区对象中,保留一个原子引用计数,记录在“发送到所有客户端”循环中已发送的重叠发送请求数。当您将缓冲区返回到完成数据包中时,将refCount减为零,并在降至0时删除/重新调用缓冲区
我认为这应该行得通,(?)。我不确定我是否理解其中一些。IOCP通常不在OVL结构中使用hEvent字段。I/O完成通过将完成消息排入“完成端口”(即队列)来发出信号。您似乎正在使用hEvent字段来管理单个发送数据缓冲区和OVL块,以获得一些“不寻常”的额外信号 显然,我不知道你文章的全部内容,但在我看来,你在tx端为自己做了大量工作,发送的连续性将扼杀性能:) 成功发送时是否必须使用相同的OVL/buffer对象?我通常做的是为每次发送使用不同的OVL/缓冲区,并立即将其排队。内核将按顺序发送缓冲区,并为每个缓冲区返回一条完成消息。套接字上的多个IOCP tx请求(这就是OVL块的用途)在内核堆栈中将它们链接在一起是没有问题的 让多个IOCP接收针对未完成套接字的请求存在一个问题—两个池线程可能同时获取同一套接字的完成数据包,因此可能导致处理顺序混乱。要“正确”修复该问题,需要在发出的每个rx buffer/OVL对象中增加序列号,并在每个套接字对象中“保存”无序缓冲区,直到处理完所有较早的缓冲区。我怀疑许多IOCP服务器只是通过一次只接收一个rx IOCP请求来回避这个问题(可能以牺牲性能为代价) 如果缓冲区被不断地构造和破坏,那么以这种方式通过大量缓冲区可能会有点费力,所以我通常不会在启动时创建几千个缓冲区,并将它们(好的,指向它们的指针)推到生产者-消费者的“池队列”上,当需要发送或接收时,将其弹出,然后将其重新打开。在发送的情况下,当一个IOCP池线程拾取发送完成消息时,就会发生这种情况。在rx的情况下,当池线程(或池线程已将对象排入队列的其他线程)已对其进行处理且不再需要它时,就会发生这种情况 啊。。您希望向套接字列表发送完全相同的内容,就像聊天服务器类型一样