DWORD bytes;
ULONG_PTR key; ChatOverlappedData* ol;
if (!GetQueuedCompletionStatus(hComp_, &bytes, &key, (LPOVERLAPPED*)&ol, 0)) {
return false;
}
int type = ol->getNetType();
if (type == net::kAction_Accept) {
onAccept(ol, bytes, key);
} else if (type == net::kAction_Recv) {
onRecv(ol, bytes, key);
} else if (type == net::kAction_Send) {
}
return true;
考虑以下方案,
客户端alice
向服务器发送了两个命令,该服务器由三个数据包p1
p2
p3
组成。前两个包形成第一个命令c1
,第三个包形成第二个命令c2
。在函数onRecv
中,服务器需要将数据包推送到某种命令缓冲区以形成完整的命令。
但假设有三个帖子t1
t2
t3
,每个帖子都会获得一个数据包(p1
,p2
,p3
)来自GetQueuedCompletionStatus
,
由于Windows是抢占式操作系统,因此线程t2
可以在t1
,t3
之前运行。结果命令缓冲区为p2
- > p1
- > p3
或p2
- > p3
- > p1
。
如何确保线程安全,以便将数据包推送到命令缓冲区?
答案 0 :(得分:3)
最简单的解决方案是每个方向只尝试一个重叠的I / O请求。因此,发布一个重叠的读取操作,当它完成时,在完成第一个处理后发布另一个。
发布多个此类操作非常复杂,因为即使完成将按顺序发布,处理完成的线程也可能无序执行,您必须进行一些痛苦而复杂的跟踪。
在同一方向上为同一连接发布多个重叠操作的好处非常非常小。几乎永远不足以证明额外的复杂性。对于处理大量连接的服务器,通常根本不值得做,因为额外的内存消耗(或使用较小的缓冲区大小)实际上会使性能变差。
IOCP的主要好处是更有效地发现哪些连接需要工作以及将该工作有效地分配给线程池。这就是最大限度地连接800个连接的服务器和能够处理10,000个连接的服务器之间的区别,而不会让您感到疲惫。