【发布时间】:2021-10-16 16:39:07
【问题描述】:
有一个函数GetQueuedCompletionStatus及其在MSDN中的描述:
尝试从指定的 I/O 出列 I/O 完成数据包 完成端口。如果没有完成包排队,函数 等待与完成端口关联的未决 I/O 操作 完成。
我以为我明白它是如何工作的,但今天我意识到我不明白它是如何工作的。
“完成包”是什么意思?
我举个例子:我正在使用 WSASend 和完成端口向服务器发送“我的请求”消息:
- 我创建了一个套接字。
- 我连接到服务器:WSAConnect()
- 这里我放了一个断点:我把网卡的线拔了,现在我的电脑上没有网络。
- 现在我正在调用 WSASend() 函数。 WSASend() 函数成功结束!好的,这可能是由于异步。
- 接下来,我调用 GetQueuedCompletionStatus() 函数 - 它也成功了!!为什么???
GetQueuedCompletionStatus() 函数应该从完成端口队列中获得一个 READY 任务,以便将我的消息发送到服务器,但是计算机上没有 Internet,并且不应该发送我的消息 - 那怎么可能呢?
或者然后是什么意思 - “来自指定 I/O 完成端口的完成数据包。”
我完全糊涂了。
【问题讨论】:
-
这是
IOP_MINI_COMPLETION_PACKET,通常这是一部分或IRP- 查看wdm.h -PacketType(Minipacket 类型)和ListEntry(List entry - 用于将数据包排队到完成队列等。)可能是IO_MINI_COMPLETION_PACKET_USER(分配给IoAllocateMiniCompletionPacket并通过IoSetIoCompletionEx插入) -
GetQueuedCompletionStatus 成功检索到完成数据包。完成数据包是 WSASend 的完成。然后,您可以查看完成数据包以查看“哦,WSASend 说它失败了”。 (你让某人等待一封信到达并把它带给你。他们等待,嘿,看起来有一封信到达,他们把它带给你。他们成功了。你打开信,这是一封拒绝信。你是伤心,但你不能责怪给你带来这封信的人。他们成功地完成了他们的工作。)
-
可能发送正在缓冲区中等待,尚未上线。
-
GetQueuedCompletionStatus 正在返回 WSASend 的结果。 WSASend 是成功还是失败不是 GetQueuedCompletionStatus 关心的问题。 GetQueuedCompletionStatus 只是送货员。
-
这是一个网络问题,与 GetQueuedCompletionStatus 无关。同样的问题适用于同步非重叠套接字。 (WSASend 文档甚至说“注意:成功完成 WSASend 并不表示数据已成功交付。”)