c - 使用IOCP时如何关闭SOCKET?

标签 c sockets winapi winsock iocp

我有一个使用 IOCP 的服务器应用程序。我想知道关闭 SOCKET 的正确方法是什么? .

如果我简单地调用closesocket() (对于 SOCKET ,其句柄例如 12345 ),而这个 SOCKET有待处理的 IO 操作(例如:待处理的 WSARecv() 请求),则可能会发生以下情况:

  • 我调用closesocket()这将摧毁 SOCKET .

  • 我接受另一个SOCKET12345 具有相同的句柄.

  • 我将待处理的 WSARecv() 出队SOCKET 的完成数据包 handle 为 12345 。现在我假设这个完成包是针对当前的 SOCKET handle 为 12345 ,但实际上它是针对SOCKET之前已关闭(这是此方法的主要问题)。

所以这显然是一个糟糕的方法。

第二种似乎正确的方法如下:

  • 我关联了 struct每个 SOCKET 的实例。 struct具有以下成员: an intnumber_of_pending_IO_operations ,以及 booleanIs_SOCKET_being_closed .

  • 当我对 SOCKET 发出 IO 操作时(例如:WSASend() 请求),我递增 number_of_pending_IO_operations通过1 ,当我将 SOCKET 的完成数据包出队时,我会递减 number_of_pending_IO_operations通过1 .

  • 现在,当我想关闭SOCKET时,我不简单地打电话closesocket() ,而是我打电话 CancelIOEx()取消 SOCKET 的所有待处理 IO 操作,我还设置了Is_SOCKET_being_closedtrue .

  • 当我要发出另一个 IO 操作(例如:WSASend() 请求)时,我会检查 Is_SOCKET_being_closed 的值,如果是 true ,我不会发出IO操作。

  • 现在我只需等待所有完成数据包出队,当 number_of_pending_IO_operations 时达到0Is_SOCKET_being_closed设置为true ,我调用closesocket() .

当然我会有竞争条件,所以我会使用关键部分。

第二种方法是关闭 SOCKET 的正确方法吗? ,或者有更好的方法吗?

最佳答案

我在客户端-服务器应用程序中遇到了类似的问题。我想我没有比赛,没有破败保护,也没有关键部分。但也有一些权衡。

  • 一次只能执行一个 WSARecv()。多个缓冲区——也许,但只有一个 WSARecv()。 WSARecv 完成(可能是内联),数据包从完成端口弹出,我快速检查我得到的内容并发出另一个 WSARecv()
  • 我有一个 Is_SOCKET_being_close 标志(实际上是一个只能上升的计数器)。计数器,因为我可能同时决定在两个不同的地方杀死套接字。
  • 设置 Is_SOCKET_being_close 后,我调用 shutdown(),然后调用 CancelIoEx(),这将破坏之前发出的 WSARecv()。
  • CancelIoEx 和 WSARecv() 的完成之间存在竞争——我在发出 WSARecv() 之前通过仔细检查 Is_SOCKET_being_close 来消除它。即使发生竞争,WSARecv() 也注定会失败,因为 shutdown()。
  • 该结构是重新计数的,其中一个 ref 由接收状态机保存,并且为 ptr 的每个合法所有者(如潜在的发送者)保存一个 ref。如果您有合法的引用,您可以制作一份副本,然后将其交给其他人(它与概要引用不同,因为它们的 AddRef() 可能会失败)。我只会在该引用耗尽到零时才会 closesocket() ,因为我无法保证没有线程已通过所有检查并即将发出 WSARecv/WSASend。

关于c - 使用IOCP时如何关闭SOCKET?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42488740/

相关文章:

java - 无法通过套接字连接到linux机器

c - C 中的 strcmp() 有问题

c - 关于strcpy溢出的问题

c - Syntastic C make 检查器不报告错误

c++ - 在c++中的区域语言设置下获取当前位置值

c++ - 在捕获鼠标但窗口未聚焦时捕获键盘事件 (Win32)

c++ - OpenGL 不显示任何内容?

c - tcp socket hungry 程序是否会干扰文件系统 I/O

c# - 如何在回发后保持 .NET Socket 对象连接打开?

android - SocketException(系统调用被取消)