【问题标题】:Is it possible (and safe) to make an accepting socket non-blocking?是否有可能(并且安全)使接受套接字成为非阻塞的?
【发布时间】:2012-10-03 10:33:03
【问题描述】:

我正在寻找一种方法来中断对阻塞套接字的accept() 调用。使用信号不是一种选择,因为这意味着在库中,我不想弄乱用户信号。使用select() 是另一种选择,由于各种原因,它对我来说并不是很吸引人。

如果可能的话,最好的方法是从另一个线程将套接字设置为非阻塞模式(使用fcntl()O_NONBLOCK),而套接字在accept() 调用上被阻塞。预期的行为是accept() 调用将在errno 中返回EAGAINEWOULDBLOCK

真的会这样吗?安全吗?便携吗?

如果你知道这个方法对Windows的适用性(这里需要使用WSAIoctl()FONBIO),我也很感兴趣。

【问题讨论】:

  • fcntl(socket, F_SETFL, O_NONBLOCK); 成功了

标签: c sockets posix fcntl


【解决方案1】:

不了解 Windows,但 POSIX 保证了您想要的行为:

如果侦听队列中没有连接请求,并且没有在套接字的文件描述符上设置 O_NONBLOCK,则 accept() 将阻塞,直到存在连接。如果listen() 队列中没有连接请求,并且在套接字的文件描述符上设置了O_NONBLOCK,则accept() 将失败并将errno 设置为[EAGAIN] 或[EWOULDBLOCK]。

来源:http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html

此外,selectpoll 可用于通过轮询读取集中的侦听套接字来检查传入连接。

【讨论】:

  • 如果已通过的文件描述符异步设置O_NONBLOCK,您确定已经阻塞的accept() 会按指定返回吗?对于这种情况,您的报价对我来说似乎模棱两可。
  • 哦,我误解了你的问题。不,我不认为在已经被阻塞时将模式更改为非阻塞是可移植的。为什么不一开始就让它成为非阻塞的,并在accept 调用之前使用pollselect,并且仅在连接可用时才调用accept?有很多干净的方法可以让selectpoll 提前返回,比如自我管道技巧。
  • 好的,所以确定的答案是不可能。理论和实践(我最终在 Linux 和 Windows 上都进行了尝试)。
  • 在 windows 上你应该使用 OVERLAPPED io。为了便携性,我建议使用 Boost Asio。
  • 在 Windows (WinSock) 上,您实际上可以从另一个线程关闭套接字。这将解除阻塞该套接字上的所有线程。
【解决方案2】:

在问题中,您是说您不想使用 select(或 poll 或 epoll),这是 IO 多路复用的最佳方式。我建议您使用另一个线程来监听套接字,但这是个坏主意!

【讨论】:

  • 感谢您的回答,但这个问题是 8 年前提出的。事实上,我什至不记得我当时想要达到的目标!
猜你喜欢
  • 1970-01-01
  • 2013-10-15
  • 1970-01-01
  • 2016-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-31
  • 2015-04-22
相关资源
最近更新 更多