什么时候连接的UDP套接字会被OS关闭?

问题描述:

我在Linux下运行的C++程序中有一个UDP文件描述符。我呼叫connect()将它连接到一个远程地址,然后从该套接字读取和写入。什么时候连接的UDP套接字会被OS关闭?

根据UNIX网络编程,“异步错误返回到连接的UDP套接字的进程”。我猜测这些异步错误会导致操作系统关闭UDP套接字,但这本书并不清楚。也不清楚哪种类型的异步错误是可能的,尽管建议如果远程机器上的端口未打开,套接字将被关闭。

所以我的问题是:在什么情况下Linux会关闭UDP文件描述符?

  • 坏端口号?
  • 错误的IP地址?
  • 其他?
+2

UDP套接字无法连接,请检查http://en.wikipedia.org/wiki/Berkeley_sockets#Client_2 – bobah 2011-04-28 19:13:04

+1

不,他们可以 - 阅读connect()的手册页:“如果s是SOCK_DGRAM类型,它会永久性地指定发送消息的对等体。“正如我在问题中提到的那样,_UNIX网络编程_指出将为所连接的UDP套接字返回异步错误_will_。 – 2011-04-30 04:07:43

UDP套接字上的connect()只记录您传入的端口号和IP地址,因此它只接受来自该IP /端口的数据包,并且您可以使用套接字fd发送/写入数据而不指定每个发送/写入呼叫的远程地址。关于这一点,异步错误意味着如果你发送()一些东西,并且发送调用会导致稍后发生错误(例如,当TCP/IP堆栈实际发送数据包或稍后返回一个ICMP数据包时),一个后续发送将返回该错误。这种异步错误仅在“连接的”UDP套接字上返回。 (linux udp(7)联机帮助页提示无论套接字是否连接都会返回错误,但测试显示,至少当发送的UDP数据包生成ICMP错误时,情况并非如此。如果你在该套接字上使用recv()而不是随后的send()调用产生错误,可能会返回send()错误)

虽然套接字未关闭,但您必须自己关闭它通过调用close()或退出程序。例如如果您连接()您的UDP套接字,并发送到无人接听端口,则通常会返回ICMP数据包,并且随后的send()调用将失败,并将errno设置为ECONNREFUSED。但是,您可以继续在该套接字上发送,但不会被操作系统关闭,并且如果有人开始在端口上收听数据包,则数据包将通过。

+1

因此它总是处于“可恢复”状态?只要另一端恢复,套接字将重新开始工作?好的,那就是我想知道的。谢谢。 – 2011-04-30 04:10:10

UDP套接字是无连接的,所以没有真正的重视他们“开放”状态感 - 这是不同于TCP套接字,其中一个插槽可以是任何数量的连接状态,如通过数据包起来的交易所决定到一个给定的点。

UDP套接字可以被打开和关闭的唯一意义在于它们是具有一些内部状态和文件描述符的系统级对象。如果发生错误,套接字永远不会自动关闭,并且将无限期地保持打开状态,除非它们的拥有进程终止或调用其上的close

若要解决您的其他问题,如果目标主机上的目标端口未打开,则UDP数据包的发送者永远不会知道。** UDP不提供接收方应答的手段。数据包被路由,如果它到达主机,检查是否正确,并且成功接收或丢弃。当写入UDP套接字时,send可能返回错误代码的原因很多,但它们都不涉及接收主机的状态。**我建议查阅sendtomanpage查找可能的故障模式。另一方面,在TCP套接字尝试连接到未打开的端口的情况下,发送方永远不会收到其初始连接请求的确认,并且最终connect将失败。此时,发送端会停止通过套接字发送数据(因为这只会产生更多错误),但即使在这种情况下,套接字文件描述符也不会自动关闭。

**请参阅@Zuljin在回复中的回复。

+1

“如果目标主机上的目标端口未打开,UDP数据包的发送者永远不会知道” - 我不能同意这一点。某些操作系统(我不确定是否全部)在目标端口未打开时返回ICMP目标不可达消息。发件人可以检测到这种情况。我认为在Windows发送者recvfrom函数将失败,错误WSAECONNRESET。我不确定在其他操作系统上如何检测到这种情况。 – Zuljin 2011-04-28 19:48:51

+0

@Zuljin,谢谢你的信息。我没有意识到这一点!我认为最终答案中更相关的部分仍然存在。即UDP“连接”不存在,并且UDP套接字永远不会由失败的I/O过程自动关闭。 – 2011-04-28 20:24:18

+0

我也没有意识到这一点,直到我的应用程序开始崩溃时服务器关闭UDP端口:)。这在socket编程教程中很难找到,在大多数情况下,处理这种情况并不是必需的。正如我所提到的,我甚至不确定是否所有流行的操作系统默认发送此ICMP软件包(我认为某些防火墙可能会阻止此行为以防止端口扫描等)。所以,当服务器支持发送ICMP时,你的整个答案是正确的,只有一点例外。 – Zuljin 2011-04-28 20:54:58

操作系统不会因为发生错误而关闭套接字。如果另一端消失,您可以继续向其发送消息(但可能会收到更多错误)。