【问题标题】:GetQueuedCompletionStatus() - what is a "completion packet"GetQueuedCompletionStatus() - 什么是“完成包”
【发布时间】:2021-10-16 16:39:07
【问题描述】:

有一个函数Ge​​tQueuedCompletionStatus及其在MSDN中的描述:

尝试从指定的 I/O 出列 I/O 完成数据包 完成端口。如果没有完成包排队,函数 等待与完成端口关联的未决 I/O 操作 完成。

我以为我明白它是如何工作的,但今天我意识到我不明白它是如何工作的。

“完成包”是什么意思?

我举个例子:我正在使用 WSASend 和完成端口向服务器发送“我的请求”消息:

  1. 我创建了一个套接字。
  2. 我连接到服务器:WSAConnect()
  3. 这里我放了一个断点:我把网卡的线拔了,现在我的电脑上没有网络。
  4. 现在我正在调用 WSASend() 函数。 WSASend() 函数成功结束!好的,这可能是由于异步。
  5. 接下来,我调用 GetQueuedCompletionStatus() 函数 - 它也成功了!!为什么???

GetQueuedCompletionStatus() 函数应该从完成端口队列中获得一个 READY 任务,以便将我的消息发送到服务器,但是计算机上没有 Internet,并且不应该发送我的消息 - 那怎么可能呢?

或者然后是什么意思 - “来自指定 I/O 完成端口的完成数据包。”

我完全糊涂了。

【问题讨论】:

  • 这是IOP_MINI_COMPLETION_PACKET,通常这是一部分或IRP - 查看wdm.h - PacketTypeMinipacket 类型)和ListEntryList entry - 用于将数据包排队到完成队列等。)可能是IO_MINI_COMPLETION_PACKET_USER(分配给IoAllocateMiniCompletionPacket并通过IoSetIoCompletionEx插入)
  • GetQueuedCompletionStatus 成功检索到完成数据包。完成数据包是 WSASend 的完成。然后,您可以查看完成数据包以查看“哦,WSASend 说它失败了”。 (你让某人等待一封信到达并把它带给你。他们等待,嘿,看起来有一封信到达,他们把它带给你。他们成功了。你打开信,这是一封拒绝信。你是伤心,但你不能责怪给你带来这封信的人。他们成功地完成了他们的工作。)
  • 可能发送正在缓冲区中等待,尚未上线。
  • GetQueuedCompletionStatus 正在返回 WSASend 的结果。 WSASend 是成功还是失败不是 GetQueuedCompletionStatus 关心的问题。 GetQueuedCompletionStatus 只是送货员。
  • 这是一个网络问题,与 GetQueuedCompletionStatus 无关。同样的问题适用于同步非重叠套接字。 (WSASend 文档甚至说“注意:成功完成 WSASend 并不表示数据已成功交付。”)

标签: c winapi winsock


【解决方案1】:

“完成端口”指的是overlapped IO——不是网络端口或套接字端口。它们是接收异步读取、写入等结果的方法……

由于缓冲,写入可以成功,需要刷新以强制写入线路。许多细节还取决于特定类型的套接字(TCP、UDP、IP、侦听器、客户端等)

您可能应该从同步调用开始,然后在您对同步感到满意后添加重叠。

【讨论】:

  • 您写道“它们是接收异步读取、写入结果的方法”。主要问题:结果写入 - 在哪里?在我的情况下,到网卡的一些缓冲区?
  • 在 Winsock 中使用重叠 IO 时,数据仍会从您提供的缓冲区写入或读取(例如:WSARead 中的 lpBuffers)——它只是不会立即发生。您必须等待异步读/写完成(例如:WSAWaitForMultipleEvents)。
  • 除非您将 WSAOVERLAPPED 传递给函数,否则您不会执行重叠 IO,应忽略它。如果您将 WSAOVERLAPPED 传递给函数,请考虑暂时不要这样做,并依赖同步读取和写入。
  • @Optimus1 - 在任何情况下 - 这只是一小块内存 - 通常是 IRPIOP_MINI_COMPLETION_PACKET。在您的情况下 - 数据包是 IRP 的一部分
  • @Optimus1 GetQueuedCompletionStatus - 未宣布已准备好向服务器发送消息。这只是说您的 I/O 操作已完成。而已。所有这些都与任何服务器、互联网连接等完全无关
【解决方案2】:

完成数据包是您传递给支持 IOCP 的函数的 LPOVERLAPPED。如果您使用 IOCP,只要原始函数返回 ERROR_IO_PENDING OVERLAPPED 实例就需要保持良好状态,直到您检索到原始函数完成的确认(无论成功与否)。 IOCP 系统不会复制 OVERLAPPED 结构的内容,而是保存地址,然后由 GetQueuedCompletionStatus 返回。如果原始函数返回 ERROR_IO_PENDING 以外的内容,则数据包不会排队到完成端口,可以立即释放。

【讨论】:

  • 这不是重叠的。如果来自 I/O 请求的数据包 - 数据包是 IRP,并且此处保存的指针传递给 I/O 请求,如果使用了 win32 i/o api - 此指针是指向重叠的指针
猜你喜欢
  • 2021-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-15
  • 2015-04-23
  • 2015-09-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多