在Linux中连接非阻塞套接字的正确方法是什么?

6

我刚接触Linux中的套接字编程,关于如何正确地进行非阻塞连接,有一个问题。

我创建了一个套接字描述符,并设置了O_NONBLOCK以进行非阻塞IO。我调用connect函数,它返回EINPROGRESS,然后我使用超时值调用select函数。

在超时之前,我怎样才能知道connect()操作需要多长时间?我是否可以在程序中更改这个时间?

如果我的select操作超时了,那该怎么办?关闭套接字描述符、创建另一个并重试连接是正常的吗?还是有一种方法可以取消现有套接字上的连接并使用相同的套接字描述符重试操作?

谢谢。


2
默认的connect()系统超时通常相当长,以适应通过几个拨号调制解调器、卫星和信鸽进行链接。 - Martin James
2个回答

2

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

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

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

我能在我的程序中更改吗?

如果你是指选择超时,那么可以更改。如果不是,我就不明白这个问题了。请注意,您可以通过此方法减少平台默认的连接超时约一分钟,但无法增加它。

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

关闭套接字并执行应用程序要求的连接超时操作。

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

只有在您有理由认为下一次会得到不同结果时才可以这样做。

或者,是否有一种方法可以取消现有套接字上的连接并使用相同的套接字描述符重试操作?

不行。一旦连接失败,套接字就已经无效,必须关闭。


1

我怎样才能在连接超时前知道connect()操作需要多久?

你无法预测。你需要提前决定一个合理的超时时间,并将该值传递给select()。我通常使用5-30秒之间,具体取决于我的应用程序运行的网络类型。

我能在我的程序中更改这个超时时间吗?

最终答案是不能。操作系统控制着等待连接超时的时间。可能有特定于操作系统的设置可以调整该超时时间,但这不是可移植或建议的。

如果我的select操作超时了,那么怎么办?

唯一能做的就是关闭套接字,然后重试。

关闭套接字描述符、创建另一个套接字并重试connect是正常的吗?

是的。

还是说有一种方法可以取消现有套接字上的连接并使用同一套接字描述符重试操作?

不行。


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接