我在Linux下运行的C ++程序中有一个UDP文件描述符。我在其上调用connect()
将其连接到远程地址,然后从该套接字读取和写入。
根据 UNIX网络编程,“异步错误将返回到连接的UDP套接字的进程。”我猜这些异步错误会导致操作系统关闭UDP套接字,但本书并不清楚。目前还不清楚哪些类型的异步错误是可能的,但建议如果远程机器上的端口未打开,则套接字将被关闭。
所以我的问题是:在什么条件下Linux会关闭UDP文件描述符?
答案 0 :(得分:5)
UDP套接字是无连接的,因此没有真正意义上的“开放”状态 - 这与TCP套接字不同,其中套接字可能处于任意数量的连接状态,这由连接到给定的数据包确定点。
UDP套接字可以打开和关闭的唯一意义在于它们是具有某种内部状态和文件描述符的系统级对象。套接字在发生错误时永远不会自动关闭,并且会无限期地保持打开状态,除非他们的拥有进程终止或在其上调用close
。
为了解决您的其他问题,如果未打开目标主机上的目标端口,UDP数据包的发送方将永远不会知道。** UDP不提供接收方确认。数据包被路由,如果它到达主机,则检查其是否正确并成功接收或丢弃。写入UDP套接字时send
可能返回错误代码的原因有很多,但没有一个与接收主机的状态有关。**我建议咨询sendto
manpage可能的失败模式。
另一方面,如果TCP套接字尝试连接到未打开的端口,发送方将永远不会收到其初始连接请求的确认,最终connect
将失败。此时,发送方将停止通过套接字发送数据(因为这只会产生更多错误),但即使在这种情况下,套接字文件描述符也永远不会自动关闭。
**请参阅@Zuljin在评论中的回复。
答案 1 :(得分:5)
connect()只记录您传入的端口号和IP地址,因此它只接受来自该IP /端口的数据包,您可以使用套接字fd发送/写入数据而不指定每个发送/写入呼叫的远程地址。
对此,异步错误意味着如果你发送()某些东西,并且发送调用导致稍后发生错误(例如,当TCP / IP堆栈实际发送数据包,或者稍后返回ICMP数据包时),则后续send将返回该错误。此类异步错误仅在“已连接”的UDP套接字上返回。 (linux udp(7)联机帮助页建议无论套接字是否连接都会返回错误,但测试显示至少在发送的UDP数据包生成ICMP错误时不会出现这种情况。可能是send()错误被返回如果你在那个套接字上recv(),而不是后续的send()调用产生错误)
套接字未关闭,您必须通过调用close()或退出程序自行关闭它。例如如果您连接()您的UDP套接字,并发送到没有人正在侦听的端口,则通常会返回ICMP数据包,并且后续的send()调用将失败,并将errno设置为ECONNREFUSED。您可以继续发送该套接字,但它不会被操作系统关闭,并且如果有人在平均时间内开始侦听端口,则数据包将通过。
答案 2 :(得分:1)
操作系统不会因为发生错误而关闭套接字。如果另一端消失,您可以继续向其发送消息(但可能会收到更多错误)。