connect()失败后套接字是否无法使用?

时间:2012-10-28 14:58:16

标签: c linux networking tcp

在史蒂文的“The Socket:Networking API,第三版”第4章第4.3段中,作者陈述如下

"If connect fails, the socket is no longer usable and must be closed. 
 We cannot call connect again on the socket."

有谁知道上述陈述背后的原因?

在我自己的实验中,我编写了一个简单的tcp客户端,它将在主机A和一个简单的tcp服务器上运行,它将在主机B上运行.tcp客户端将尝试永远连接到主机B上的tcp服务器。

所以,我在主机B上启动了服务器。从主机拉出网络线。然后我在主机A上启动了客户端。在同一个套接字上大约9次连接尝试失败后,我只需将网络线插回服务器主机。客户端连接成功并愉快地以80K /秒的速度发送消息。

在另一个实验中,我在初始成功连接和之后几百万条消息交换后从服务器主机拔出电线。然后,几分钟后,我连接了电线,并在同一插座上恢复了消息流。

4 个答案:

答案 0 :(得分:6)

POSIX 2001 says在信息部分:

  

如果connect()失败,则未指定套接字的状态。在尝试重新连接之前,符合要求的应用程序应关闭文件描述符并创建新套接字。

因此,您引用的段落与此规范一致。它在您的机器上运行的事实并不意味着您的程序是可移植的。

答案 1 :(得分:2)

这可能植根于manpage of connect,其中包含:

  

通常,基于连接的协议套接字可能只成功connect()一次;无连接协议套接字可以多次使用connect()来更改它们的关联。

这意味着您不能只重新连接基于连接的(读取,TCP)套接字。但是,我无法看到任何关于失败connect()的说法,暗示我们无法回收FD。

如果连接中断,则恢复连接是TCP的一项功能,通常会尝试这样做。

答案 2 :(得分:1)

回答您的具体问题......

很简单,那里有大量的TCP实现。虽然有些人可能支持在一次失败后再进行connect()次呼叫,但其他人可能会获得状态信息,这样做会使这种做法变得不可靠。

为了安全起见,必须进行某种reset()操作,使套接字返回到原始状态。由于这不包括在原始(或任何后续)TCP实现中,因此唯一剩下的选项是关闭并重新打开。

POSIX标准(以及您的书,可能使用POSIX标准作为参考)因此告诉您这样做,以便能够使用所有支持TCP / IP的操作系统。否则就会使一些现有的实现失效。

此外,新的实现可以自由地简化其实现,而不必担心在尝试失败后启动新连接;这样可以减少代码,减少错误蔓延的可能性。

答案 3 :(得分:0)

您确定使用相同的套接字,而不是尝试连接到与以前相同的地址的套接字吗?

即使你正在做的事情,你正在尝试的特定操作系统允许重用未能连接的套接字这一事实并不意味着所有其他实现套接字API的操作系统(或更早版本) /同一操作系统的更高版本)同样宽松,因此您可能会冒险生成微妙的非可移植代码。

当您执行API合同未承诺您将工作的事情时,通常不知道会发生什么。一种可能的反应是它出现工作 - 直到付费客户试图在他的机器上运行你的代码。

在相当罕见的错误情况下,这种风险真的值得close(socket); socket=socket(...);的费用吗?