我有一个使用IOCP的服务器应用程序。我想知道关闭SOCKET
的正确方法是什么。
如果我只是简单地调用closesocket()
(对于SOCKET
,其句柄为12345
),并且此SOCKET
具有待处理的IO操作(例如:a pending) 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
,当我deque SOCKET的完成数据包,我number_of_pending_IO_operations
递减1
。
现在,当我要关闭SOCKET
时,我不是简单地调用closesocket()
,而是调用CancelIOEx()
来取消所有挂起的IO操作SOCKET
,我还将Is_SOCKET_being_closed
设置为true
。
当我即将发出另一个IO操作(例如:WSASend()
请求)时,我会检查Is_SOCKET_being_closed
的值,如果是true
,我不会发出IO操作。
现在我只是等待所有完成数据包出列,当number_of_pending_IO_operations
到达0
且Is_SOCKET_being_closed
设置为true
时,我打电话给closesocket()
。
当然我会有竞争条件,所以我会使用关键部分。
第二种方法是关闭SOCKET
的正确方法,还是有更好的方法?
答案 0 :(得分:1)
我的客户端 - 服务器应用程序中存在类似的问题。我想我没有比赛,没有破坏保护,也没有关键部分。但是有一些权衡。