在linux中连接非阻塞套接字的正确方法是啥

Posted

技术标签:

【中文标题】在linux中连接非阻塞套接字的正确方法是啥【英文标题】:What's the proper way to connect a non-blocking socket in linux在linux中连接非阻塞套接字的正确方法是什么 【发布时间】:2014-08-25 19:06:59 【问题描述】:

我是在 Linux 中使用套接字编程的新手,并且对进行非阻塞连接的正确方法有疑问。

我创建了一个套接字描述符并将 O_NONBLOCK 设置为非阻塞 IO。我调用connect,它返回EINPROGRESS,然后我调用select,带有一个超时值。

如何知道 connect() 操作在超时之前需要多长时间?我可以在我的程序中更改它吗?

如果我的选择操作超时,那该怎么办?关闭套接字描述符,创建另一个,然后重试连接是否正常?或者,有没有办法取消现有套接字上的连接并使用相同的套接字描述符重试操作?

谢谢。

【问题讨论】:

默认 connect() 系统超时通常很长,以适应通过几个拨号调制解调器、卫星和信鸽的链接。 【参考方案1】:

连接完成后,socket FD 将变为可写状态。您还应该通过 getsockopt() 检查套接字的最后一个错误。

如何知道 connect() 操作在超时之前需要多长时间?

你当然不能。你必须尝试一下。这个问题没有意义。

我可以在我的程序中更改它吗?

如果您的意思是这样,您可以更改选择超时。如果不是,我不明白这个问题。请注意,您可以通过这种方式减少大约一分钟的平台默认连接超时,但不能增加它。

如果我的选择操作超时,那怎么办?

您关闭套接字并执行您的应用程序要求的任何连接超时。

关闭socket描述符,再创建一个,然后重试连接正常吗?

只有当你有理由认为下次你会得到不同的结果时。

或者,有没有办法取消现有套接字上的连接并使用相同的套接字描述符重试操作?

没有。一旦连接失败,套接字就死了,必须关闭。

【讨论】:

【参考方案2】:

如何知道 connect() 操作在超时之前需要多长时间?

你没有。您必须提前决定一个合理的超时时间以满足您的需求,然后将该值传递给select()。我通常使用 5-30 秒之间的任何时间,具体取决于我的应用运行的网络类型。

我可以在我的程序中更改它吗?

最终,没有。操作系统可以控制等待连接超时的时间。您可能可以调整特定于操作系统的设置来控制该超时,但这不是可移植的,也不推荐使用。

如果我的选择操作超时,那怎么办?

您唯一能做的就是关闭套接字并重试。

关闭套接字描述符,再创建一个,然后重试连接是否正常?

是的。

或者,有没有办法取消现有套接字上的连接并使用相同的套接字描述符重试操作?

没有。

【讨论】:

感谢 Remy 和 EJP。这些答案有帮助,对令人困惑的问题感到抱歉。我正在编写的程序将在安装在远程位置的设备上运行,这些设备必须通过不可靠的网络(小区或卫星)建立连接,因此连接尝试可能会在一分钟失败,然后在下一分钟成功。根据您所说,当连接尝试失败时,我的正确方法是关闭套接字描述符,创建一个新描述符,然后重新尝试连接。

以上是关于在linux中连接非阻塞套接字的正确方法是啥的主要内容,如果未能解决你的问题,请参考以下文章

如何中止winsock阻塞调用?

C++非阻塞键盘缓冲区输入检测或读取函数是啥?

在 C 中使用非阻塞套接字连接

Socket编程中,阻塞与非阻塞的区别

windows下在非阻塞TCP套接字上使用SO_SNDBUF的奇怪行为

检测非阻塞套接字上的关闭连接