I/O 完成端口,如何释放每个套接字上下文和每个 I/O 上下文?
Posted
技术标签:
【中文标题】I/O 完成端口,如何释放每个套接字上下文和每个 I/O 上下文?【英文标题】:I/O Completion Port, How to free Per Socket Context and Per I/O Context? 【发布时间】:2009-03-24 12:24:39 【问题描述】:我在 UDP 套接字上使用 IOCP,UDP 套接字可能在另一个线程中关闭。那么,如何安全地释放与 SOCKET 关联的 Per Socket Context 和 Per I/O Context 呢?
当我关闭套接字时,内核队列中仍有未完成的 I/O 请求。
如果我在套接字关闭时释放上下文,GetQueueCompletionStatus 可能会失败。
现在,我的问题是何时释放上下文?
【问题讨论】:
【参考方案1】:我对所有每个套接字和每个 I/O 数据结构都使用引用计数。它使这种事情变得容易,因为当它们的引用下降到 0 时它们会被删除。对于一些显示一种方法的示例代码,您可以查看我的免费 IOCP 框架,您可以从 here 下载该框架。
【讨论】:
【参考方案2】:使用mutex 在代码的关键部分强制互斥,这将检查套接字的可用性,并在必要时打开它。将套接字锁定到该线程,并在完成后适当地释放它。
【讨论】:
【参考方案3】:我重复使用每个套接字的结构。在我收到该连接所需的所有读写操作的完成事件后,我使用TF_DISCONNECT
和TF_REUSE_SOCKET
标志调用TransmitFile
来重置套接字而无需关闭它。一旦TransmitFile
调用的完成事件通过,我还会重置每个连接的数据。
【讨论】:
【参考方案4】:先关闭套接字。你会从 GetQueuedCompletionStatus 得到错误(我认为是 ERROR_OPERATION_ABORTED),然后是释放结构的正确时间。此时内核队列中该连接上没有其他未完成的请求,完成包按FIFO顺序维护,错误包肯定是该连接的最后一个。
【讨论】:
什么有多个数据包待处理?例如如果一个读和一个写待处理,你不知道哪个会先返回 ERROR_OPERATION_ABORTED,对吧? 好的。即使使用 ERROR_OPERATION_ABORTED ,您仍然可以获得从 GetQueuedCompletionStatus() 返回的有效完成键和重叠参数。您可以将任一用于您想要释放的上下文。 我的意思是,如果您有 both 写入和读取(因此 2 个 OVERLAPPED 结构等待 i/o 完成),您不知道两者中的哪一个将首先完成,哪个将最后完成(即使两者都返回 ERROR_OPERATION_ABORTED 与否),因此您需要一个原子计数器来确定哪个将完成 last 然后从在那里释放内存 好的,我想我现在明白你的意思了。如果您分配单个“连接”并将其用于读取和写入,并且可能有多个 IO 在运行中,那么您需要重新计数,并在您的 refcount 下降到 0 时取消分配,并且您会收到错误。如果您没有多个未完成的 IO,或者使用完全独立的结构进行读写,那么您不需要引用计数。 没错,这就是我的意思。我的意思是当我分配每个套接字结构时的场景,比如 struct Socket ... SOCKET socket; ;看到这个讨论 -> ***.com/questions/21907157/…以上是关于I/O 完成端口,如何释放每个套接字上下文和每个 I/O 上下文?的主要内容,如果未能解决你的问题,请参考以下文章
io 完成端口问题,每个 GetQueuedCompletionStatus 调用多个 wsarecv 或 wsasend