【问题标题】:Windows socket completion routine callback after closesocketclosesocket 后的 Windows 套接字完成例程回调
【发布时间】:2019-01-03 12:48:59
【问题描述】:

在忙于在重叠模式下使用 Windows 套接字并使用完成例程(因此没有 IOCP)进行反馈时,我发现了以下奇怪的案例:

  1. 使用listenAcceptEx 打开服务器套接字。
  2. 使用ConnectEx在所述端口上连接客户端套接字

我们现在(至少)有 3 个套接字:1 个列表套接字、一个客户端连接套接字和一个服务器连接套接字。

在传输一些数据后,我们使用shutdown 关闭服务器和客户端连接的套接字。在这一步之后,两个套接字都用closesocket关闭。

目前:为了确保我们没有待处理的完成例程,我发出以下(伪代码):

而 SleepEx(0, TRUE) == WAIT_IO_COMPLETION 做;

我想现在释放WSARecvWSASend 使用的OVERLAPPED 结构的内存会省事。

在线程再次进入警报状态的那一刻之后,另一个完成例程回调为服务器连接的套接字执行错误 10053,但使用我们刚刚释放的 OVERLAPPED 结构。这是free后的内存使用情况。

问题:

您什么时候可以确定不再使用完成例程为使用重叠 IO 的套接字发出完成回调?

【问题讨论】:

  • @RbMm:这里没有 IOCP。
  • @BenVoigt - 但是 AcceptExConnectEx 怎么样?在异步模式下使用它的唯一方法 - 为 iocp 绑定套接字。不清楚 OP 在做什么
  • @RbMm:你可以在没有完成端口的情况下进行异步 I/O。
  • @BenVoigt - 依赖于 api。 AcceptExConnectEx 只允许使用 iocp 异步。此 api 没有 APC 选项,这里没有回调作为参数。不是 ?或 OP 使用同步 AcceptExConnectEx
  • @RbMm:没有回调,但在重叠结构中有一个事件句柄。而导致他问题的实际操作是WSARecv,它确实有一个回调参数。

标签: windows sockets overlapped-io


【解决方案1】:

您需要等待 I/O 完成(关闭套接字将取消未完成的请求,您将收到完成回调)。

操作系统拥有 OVERLAPPED 结构和相关缓冲区的所有权,直到您在事件完成时进行同步(通过等待 hEvent 或接收 APC)。在收到此回调之前,您不能对缓冲区进行任何操作,并且绝对不能释放它。等待操作系统告诉您不再需要它。

请注意,取消不一定会立即完成,因为驱动程序可能正在与硬件请求同步,并且仅在硬件状态更改时才将 IRP 标记为完成。 (如果 DMA 正在使用中,这将是必要的,但为了保持一致性,可能会为其他操作执行此操作)因此,您显示的 SleepEx 循环不能保证收集所有取消。

跟踪挂起操作的每个套接字,并使用WaitForSingleObjectEx 而不是SleepEx,显式等待每个套接字。

【讨论】:

  • 好的。因此,对于每个未完成的 WSARecv 和 WSASend,我都会记账,当回调返回时,我可以清理重叠的结构和套接字包装对象。但这意味着必须保证回调将被调用,否则我可能会无限期地等待回调,因此会发生内存泄漏。我找不到操作系统是否能保证这一点。这是有保证的吗?
  • 如果初始调用得到WSAEWOULDBLOCK,保证在操作结束时得到回调,无论是成功、失败还是取消。
  • 来自 MSDN:0(OK)和 WSAEWOULDBLOCK 都返回保证的回调。所以记账。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-23
  • 1970-01-01
  • 1970-01-01
  • 2011-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多