【问题标题】:Detecting server socket close with select使用选择检测服务器套接字关闭
【发布时间】:2017-11-27 10:38:16
【问题描述】:

我有一个简单的套接字服务器,我在 linux 和 Windows 上用 C 语言实现了它,但我很难干净地关闭它。

它创建一个套接字,绑定它,然后调用listen。然后,它使用 select 循环以检测新连接,以及任何当前连接的客户端套接字上的读取活动。关闭套接字的客户端很好,可以唤醒选择,我遇到的问题是干净地关闭循环。我天真地从另一个线程关闭了服务器套接字(我正在侦听和接受的那个),或者响应信号或 Ctrl-C,但这未能唤醒选择,这让我感到惊讶。

如有必要,我可以使用自我管道技巧等待选择(创建一个先进先出并将读取端也包含在选择列表中,然后在我想关闭时写入它),但这不会是考虑到代码的结构,非常方便。 我只是想知道这是否是预期的行为,我是否希望我的选择在我关闭服务器套接字时唤醒。它确实在 Windows 上以这种方式工作。

谢谢。

【问题讨论】:

  • 你的监听套接字是否在 select() 的 read fd 集中?
  • 你能简单地定位一个全局变量并用 pthread_kill 向选择线程发送信号吗?

标签: c linux sockets


【解决方案1】:

从另一个线程关闭套接字/文件描述符是个坏主意,因为它容易出现竞争条件。

select 调用被信号中断。您可以使用自管道技巧在select 线程中检测SIGINT,并根据需要关闭套接字。

或者,信号处理程序可以设置一个全局sigatomic_t 变量,而不是通过管道传递信号编号,pselect 线程将在pselect 被信号中断时检查该变量。在这种情况下,必须始终阻止 SIGINT,除非在 pselect 调用中。

【讨论】:

  • 给我带来问题的实际环境是我的测试环境,我显然必须在一个线程上运行服务器,而测试在主线程上运行,然后我想关闭服务器一次测试已经结束。我将不得不尝试找出如何干净地将管道包含到代码结构中,以便更干净地执行此操作。谢谢。
  • 不幸的是,自管道技巧仅适用于 UNIX,因为在 Windows 上,选择仅适用于套接字。我想最便携的解决方案是创建一个端口并将其绑定到临时端口上的 localhost,然后连接到它并将其用作此类事物的控制端口,因此请使用自管套接字而不是 fifo。不过感觉很重。
  • @TomQuarendon: "然后我想关闭服务器" 所以你的实现不提供任何关闭服务器的功能?
  • @TomQuarendon 我会检查 Windows select 是否适用于 Windows _pipe
  • @TomQuarendon:那你最好不要使用select()。在 *Nix 上使用(e)poll(),在 Windows 上使用WSAEventSelect()+WSAWaitForMultipleEvents()(每个套接字都有一个WSAEVENT,关闭一个WSAEVENT - 这将是实现自我的最接近的方法Windows 上的管道技巧,只需最少的努力)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多