一个连接的UDP套接字何时会被操作系统关闭?

When will a connected UDP socket be closed by the OS?

本文关键字:何时会 操作系统 套接字 UDP 一个 连接      更新时间:2023-10-16

我在Linux下运行的c++程序中有一个UDP文件描述符。我调用connect()将其连接到远程地址,然后从该套接字读取和写入。

根据UNIX Network Programming,"对于连接的UDP套接字,异步错误将返回给进程。"我猜这些异步错误将导致UDP套接字被操作系统关闭,但这本书不是那么清楚。也不清楚什么类型的异步错误是可能的,尽管建议如果远程机器上的端口未打开,则套接字将被关闭。

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

  • 端口号错误?
  • 错误的IP地址?
  • 还有其他的吗?

connect()在UDP套接字上只记录端口号和你传入的IP地址,所以它只接受来自该IP/端口的数据包,并且你可以使用套接字fd来发送/写入数据,而无需为每个发送/写入调用指定远程地址。

关于这一点,异步错误意味着如果你发送()一些东西,并且发送调用导致稍后发生错误(例如,当TCP/IP堆栈实际发送数据包时,或者稍后返回ICMP数据包),随后的发送将返回该错误。这种异步错误仅在"连接"的UDP套接字上返回。linux udp(7)手册建议无论套接字是否连接都返回错误,但测试表明,至少当发送的udp数据包产生ICMP错误时,情况并非如此。如果您在该套接字上recv(),则可能会返回send()错误,而不是随后的send()调用产生错误)

套接字没有关闭,您必须通过调用close()或退出程序来关闭它。例如,如果你connect()你的UDP套接字,并发送到一个端口noone正在监听,一个ICMP数据包通常被返回,随后的send()调用将失败errno设置为ECONNREFUSED。您可以继续在该套接字上发送,它不会被操作系统关闭,如果有人在此期间开始侦听端口,数据包将通过。

UDP套接字是无连接的,因此没有真正意义上的"开放"状态附加到它们上-这与TCP套接字不同,在TCP套接字中,套接字可以处于任意数量的连接状态,由数据包交换决定,直到给定点。

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

为了解决你的另一个问题,如果目的主机上的目的端口没有打开,UDP数据包的发送者将永远不会知道。UDP不提供接收方确认的方式。数据包被路由,如果它到达主机,则检查其正确性,成功接收或丢弃。send可能在写入UDP套接字时返回错误代码的原因有很多,但它们都与接收主机的状态无关。**我建议查阅sendto管理页,了解可能的故障模式。

另一方面,在TCP套接字试图连接到未打开的端口的情况下,发送方将永远不会收到其初始连接请求的确认,最终connect将失败。此时,将由发送方决定是否停止通过套接字发送数据(因为这只会产生更多错误),但即使在这种情况下,套接字文件描述符也不会自动关闭。

**参见@Zuljin在评论中的回应

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