closesocket后的Windows套接字完成例程回调
在忙着以重叠模式使用Windows套接字并使用完成例程(因此没有IOCP)进行反馈时,我发现了以下奇怪的情况:closesocket后的Windows套接字完成例程回调,windows,sockets,overlapped-io,Windows,Sockets,Overlapped Io,在忙着以重叠模式使用Windows套接字并使用完成例程(因此没有IOCP)进行反馈时,我发现了以下奇怪的情况: 使用listen和AcceptEx打开服务器套接字 使用ConnectEx 我们现在有(至少)3个套接字:1个列表套接字、一个客户端连接的套接字和一个服务器连接的套接字 传输一些数据后,我们通过shutdown关闭服务器和客户端连接的套接字。完成此步骤后,两个插座都将使用closesocket关闭 目前:为了确保我们没有挂起的完成例程,我发布了以下(伪代码): 而SleepEx(0,T
listen
和AcceptEx
打开服务器套接字ConnectEx
shutdown
关闭服务器和客户端连接的套接字。完成此步骤后,两个插座都将使用closesocket
关闭
目前:为了确保我们没有挂起的完成例程,我发布了以下(伪代码):
而SleepEx(0,TRUE)=WAIT\u IO\u COMPLETION do
我现在想,释放WSARecv
和WSASend
使用的OVERLAPPED
结构的内存是可以节省的
在此之后,当线程再次处于可警报状态时,将对服务器连接的套接字执行另一个完成例程回调,错误为10053,但使用我们刚刚释放的重叠
结构。这是空闲后内存的使用
问题:
何时才能确保不再使用完成例程对使用重叠IO的套接字发出完成回调?您需要等待I/O完成(关闭套接字将取消未完成的请求,您将获得完成回调) 操作系统拥有重叠结构和相关缓冲区的所有权,直到您在事件完成时同步(通过等待
hEvent
或接收APC)。在收到此回调之前,您不能对缓冲区执行任何操作,而且您绝对不能释放它。等待操作系统告诉您不再需要它
请注意,取消不一定会立即导致完成,因为驱动程序可能正在与硬件请求同步,并且仅在硬件状态更改时才将IRP标记为完成。(如果DMA正在使用,这将是必要的,但可能只是为了一致性而对其他操作执行此操作),因此您显示的SleepEx
循环不能保证收集所有取消
跟踪挂起操作的每个套接字,并使用
WaitForSingleObjectEx
而不是SleepEx
,以明确地等待每个操作。您需要等待I/O完成(关闭套接字将取消未完成的请求,并且您将获得完成回调)
操作系统拥有重叠结构和相关缓冲区的所有权,直到您在事件完成时同步(通过等待hEvent
或接收APC)。在收到此回调之前,您不能对缓冲区执行任何操作,而且您绝对不能释放它。等待操作系统告诉您不再需要它
请注意,取消不一定会立即导致完成,因为驱动程序可能正在与硬件请求同步,并且仅在硬件状态更改时才将IRP标记为完成。(如果DMA正在使用,这将是必要的,但可能只是为了一致性而对其他操作执行此操作),因此您显示的SleepEx
循环不能保证收集所有取消
跟踪挂起操作的每个套接字,并使用
WaitForSingleObjectEx
而不是SleepEx
,显式地等待每个操作。@RbMm:这里没有IOCP。@BenVoigt-但是AcceptEx
和ConnectEx
呢?在异步模式下使用它的唯一方法是为iocp绑定套接字。不清楚什么是OPdoing@RbMm:您可以在没有完成端口的情况下完成异步I/O。@BenVoigt-depend from apiAcceptEx
和ConnectEx
仅与iocp低异步。此api没有APC选项,此处没有回调作为参数。不是吗?或OP使用同步的AcceptEx
和ConnectEx
?@RbMm:没有回调,但重叠结构中有一个事件句柄。导致他出现问题的实际操作是有回调参数的WSARecv
。@RbMm:这里没有IOCP。@BenVoigt-但是AcceptEx
和ConnectEx
呢?在异步模式下使用它的唯一方法是为iocp绑定套接字。不清楚什么是OPdoing@RbMm:您可以在没有完成端口的情况下完成异步I/O。@BenVoigt-depend from apiAcceptEx
和ConnectEx
仅与iocp低异步。此api没有APC选项,此处没有回调作为参数。不是吗?或OP使用同步的AcceptEx
和ConnectEx
?@RbMm:没有回调,但重叠结构中有一个事件句柄。导致他出现问题的实际操作是WSARecv
,它有一个回调参数。Ok。因此,对于每个未完成的WSARecv和WSASend,我都会记账,当回调返回时,我可以清理重叠的结构和套接字包装器对象。但这意味着必须保证回调将被调用,否则我可能会无限期地等待回调,因此会出现内存泄漏。我找不到操作系统是否保证这一点。这有保证吗?如果您从初始调用中获得了WSAEWOULDBLOCK
,则保证在操作结束时获得回调,无论是成功、失败还是取消。从MSDN:0(确定)和WSAEWOULDBLOCK都返回保证回调。那么记账就是了。因此,对于每个未完成的WSARecv和WSASend,我都会记账,当回调返回时,我可以清理重叠的结构和套接字包装器对象。但这意味着必须保证回调将被调用,否则我可能会无限期地等待回调,因此会出现内存泄漏。我不知道这是否有保证