GetQueuedCompletionStatus 延迟
Posted
技术标签:
【中文标题】GetQueuedCompletionStatus 延迟【英文标题】:GetQueuedCompletionStatus delayed 【发布时间】:2011-04-29 10:07:38 【问题描述】:我已经编写了复杂的库来管理基于 iocp 机制的网络通信。问题是当服务器通过调用 API 方法 closesocket() 关闭连接时,此信息有时会延迟数秒甚至数分钟传输到客户端。我用于检测连接关闭的代码如下所示(简化):
ok = GetQueuedCompletionStatus(completion_port, &io_size, (PULONG_PTR)&context, &overlapped, 40);
if (!ok)
// something went broken
DWORD err = GetLastError();
if (err == ERROR_CONNECTION_REFUSED)
// connection failed
else if (err == ERROR_SEM_TIMEOUT)
// connection timeout
else if (err == ERROR_NETNAME_DELETED)
// connection closure - point of interest
else if (err != WAIT_TIMEOUT)
// unknown error
else
// process incomming or outgoing data
为什么会这样?我需要立即了解连接关闭,以便能够连接到备份服务器(负载不那么重 - 因此会发生断开连接)。
【问题讨论】:
与您的问题没有直接关系,但您应该检查重叠的值以及处理程序中的返回码。当重叠 == NULL 表示 GetQueuedCompletionStatus 失败,当重叠 != NULL 表示 I/O 请求失败。 【参考方案1】:你是如何关闭连接的?
如果您只是调用closesocket()
,那么您正在启动一个关闭序列,该序列将尝试确保当前待处理的所有数据都将到达目的地。这可能需要一些时间,尤其是在网络连接过载、数据报丢失以及 TCP 重传发生的情况下。
如果您想立即关闭连接并丢失任何未决数据,请将 linger 设置为 0,然后关闭套接字。这将在连接上发出 RST,您会更快。
【讨论】:
【参考方案2】:我尝试使用 Len 所写的 linger 参数进行试验,但这并没有帮助。在 closesocket() 之前添加对 shutdown() 函数的调用对我有帮助。在分析到达客户端网络接口的数据包(使用 WireShark)后,我发现 RST 数据包已被 FIN 数据包替换。奇怪的是,RST 数据包没有延迟。因此操作系统知道连接已关闭,但由于某种未知原因,此信息非常延迟地传输到应用程序层。我测量了 10 秒到 4 分钟之间的延迟。
【讨论】:
以上是关于GetQueuedCompletionStatus 延迟的主要内容,如果未能解决你的问题,请参考以下文章
如何强制 GetQueuedCompletionStatus() 立即返回?
一些使用 WSASend 的 OVERLAPS 没有使用 GetQueuedCompletionStatus 及时返回?
当 GetQueuedCompletionStatus() 返回 FALSE 时,这些参数的值是多少?
GetQueuedCompletionStatus 返回后发生错误,错误号为 ERROR_INVALID_NETNAME
GetQueuedCompletionStatus 继续选择关闭套接字上的事件
io 完成端口问题,每个 GetQueuedCompletionStatus 调用多个 wsarecv 或 wsasend