我有一个使用IOCP的服务器应用程序。我想知道关闭SOCKET的正确方法是什么。如果我简单地调用closesocket()(对于具有例如SOCKET句柄的12345),并且此SOCKET具有待处理的IO操作(例如:待处理的WSARecv()请求),则以下情况可能发生:我称closesocket()将销毁SOCKET。我接受另一个具有SOCKET相同句柄的12345。我使用WSARecv()的句柄出队SOCKET的待处理12345完成包。现在,我假设此完成包是针对具有SOCKET句柄的当前12345的,但实际上是针对先前关闭的SOCKET的(这是此方法的主要问题)。因此,这显然是一个不好的方法。似乎正确的第二种方法如下:我将struct实例与每个SOCKET关联。 struct具有以下成员:称为int的number_of_pending_IO_operations和称为boolean的Is_SOCKET_being_closed。当我为SOCKET发出IO操作(例如:WSASend()请求)时,我将number_of_pending_IO_operations递增1,当我将SOCKET的完成数据包出队时,我将number_of_pending_IO_operations递减。现在,当我想关闭1时,我不只是调用SOCKET,而是调用closesocket()来取消CancelIOEx()的所有待处理的IO操作,并且还将SOCKET设置为。当我要发出另一个IO操作(例如:一个Is_SOCKET_being_closed请求)时,我将检查true的值,如果它是WSASend(),则不会发出IO操作。现在,我只是等待所有完成数据包出队,并且当Is_SOCKET_being_closed到达true并且number_of_pending_IO_operations设置为0时,我呼叫Is_SOCKET_being_closed。当然,我会遇到比赛条件,所以我会使用关键部分。第二种方法是关闭true的正确方法,还是有更好的方法? 最佳答案 我的客户端服务器应用程序中有类似的问题。我认为我没有比赛,没有比赛保护,也没有关键区域。虽然有一些权衡。一次仅一个WSARecv()。多个缓冲区-可能只有一个WSARecv()。 WSARecv完成(可能是内联),数据包从完成端口弹出,我迅速检查了一下并发出了另一个WSARecv()我有一个Is_SOCKET_being_closed标志(实际上是一个只能上升的计数器)。反对,因为我可能同时决定在两个不同的地方杀死套接字。设置Is_SOCKET_being_closed后,我先调用shutdown(),再调用CancelIoEx(),这将破坏先前发布的WSARecv()。在CancelIoEx和WSARecv()完成之间存在竞争-我在发布WSARecv()之前仔细检查Is_SOCKET_being_closed消除了它。即使发生争用,WSARecv()注定也会因为shutdown()而失败。该结构被重新引用,其中一个ref由接收状态机持有,并且为ptr的每个合法所有者(例如,潜在的发送者)持有一个ref。如果您有合法的裁判,则可以制作一份副本,然后将其交给其他人(此处与精简引用不同,因为它们的AddRef()可能会失败)。我只会在该引用耗尽为零时关闭closesocket(),因为我不能保证没有线程通过所有检查并即将发出WSARecv / WSASend。关于c - 使用IOCP时如何关闭SOCKET?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42488740/
10-11 18:19