Linux 操作系统何时关闭已连接的 UDP 套接字?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5823723/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When will a connected UDP socket be closed by the OS?
提问by Ian Barkley-Yeung
I have a UDP file descriptor in a C++ program running under Linux. I call connect()
on it to connect it to a remote address and then read and write from that socket.
我在 Linux 下运行的 C++ 程序中有一个 UDP 文件描述符。我调用connect()
它以将其连接到远程地址,然后从该套接字读取和写入。
According to UNIX Network Programming, "Asynchronous errors are returned to the process for connected UDP sockets." I'm guessing that these asynchronous errors will cause the UDP socket to be closed by the OS, but the book isn't that clear. It also isn't clear what types of asynchronous errors are possible, though it's suggested that if the port on the remote machine is not open, the socket will be closed.
根据UNIX Network Programming,“异步错误将返回到已连接 UDP 套接字的进程。” 我猜这些异步错误会导致 UDP 套接字被操作系统关闭,但书中并没有那么清楚。也不清楚可能出现哪些类型的异步错误,但建议如果远程机器上的端口未打开,则套接字将关闭。
So my question is: Under what conditions will Linux close the UDP file descriptor?
所以我的问题是:Linux在什么情况下会关闭UDP文件描述符?
- Bad port number?
- Bad IP address?
- Any others?
- 端口号不正确?
- 错误的IP地址?
- 还有其他人吗?
采纳答案by nos
connect() on an UDP socket just records the port number and IP address you pass in, so it'll only accept packets from that IP/port, and you can use the socket fd to send/write data without specifying the remote address for each send/write call.
UDP 套接字上的 connect() 只记录您传入的端口号和 IP 地址,因此它只会接受来自该 IP/端口的数据包,您可以使用套接字 fd 发送/写入数据,而无需指定远程地址每次发送/写入调用。
Regarding this, async errors means if you send() something, and that send call results in an error occuring later (e.g. when the TCP/IP stack actually sends the packet, or an ICMP packet is later returned), a subsequent send will return that error. Such async errors are only returned on a "connected" UDP socket. (The linux udp(7) manpage suggest errors are returned whether the socket is connected or not, but testing shows this is not the cases at least when a sent UDP packet generates an ICMP error. It might be that send() errors are returned if you recv() on that socket, instead of subsequent send() calls produce an error )
关于这一点,异步错误意味着如果您 send() 某些内容,并且该 send 调用导致稍后发生错误(例如,当 TCP/IP 堆栈实际发送数据包时,或稍后返回 ICMP 数据包时),后续发送将返回那个错误。此类异步错误仅在“已连接”的 UDP 套接字上返回。(linux udp(7) 联机帮助页建议无论套接字是否连接都返回错误,但测试表明至少当发送的 UDP 数据包生成 ICMP 错误时,情况并非如此。可能是返回了 send() 错误如果您在该套接字上使用 recv(),而不是随后的 send() 调用会产生错误)
The socket is not closed though, you'll have to close it yourself either by calling close() or exiting the program. e.g. if you connect() your UDP socket, and send to a port noone is listening to, an ICMP packet is normally returned and a subsequent send() call will fail with errno set to ECONNREFUSED. You can continue sending on that socket though, it doesn't get closed by the OS, and if someone starts listening on the port in the mean time the packets will get through.
但是套接字并未关闭,您必须通过调用 close() 或退出程序自行关闭它。例如,如果你connect() 你的UDP 套接字,并发送到一个没有人监听的端口,通常会返回一个ICMP 数据包,随后的send() 调用将失败,errno 设置为ECONNREFUSED。不过,您可以继续在该套接字上发送,它不会被操作系统关闭,并且如果有人在此期间开始侦听端口,数据包将通过。
回答by Ken Rockot
UDP sockets are connectionless, so there is no real sense of "openness" state attached to them - this is unlike TCP sockets where a socket may be in any number of connection states as determined by the exchange of packets up to a given point.
UDP 套接字是无连接的,因此它们没有真正意义上的“开放”状态——这与 TCP 套接字不同,在 TCP 套接字中,套接字可能处于任意数量的连接状态,这取决于直到给定点的数据包交换。
The only sense in which UDP sockets can be opened and closed is in the sense that they are system level objects with some internal state and a file descriptor. Sockets are never automatically closed in the event of an error and will remain open indefinitely, unless their owning process terminates or calls close
on them.
UDP 套接字可以打开和关闭的唯一意义在于它们是具有某些内部状态和文件描述符的系统级对象。发生错误时,套接字永远不会自动关闭,并且会无限期地保持打开状态,除非它们的拥有进程终止或调用close
它们。
To address your other concern, if the destination port on the destination host is not opened, the sender of a UDP packet will never know.** UDP provides no means of receiver acknowledgement. The packet is routed and, if it arrives at the host, checked for correctness and either successfully received or discarded. There are a number of reasons why send
might return an error code when writing to a UDP socket, but none of them have to do with the state of the receiving host.** I recommend consulting the sendto
manpagefor possible failure modes.
为了解决您的其他问题,如果目标主机上的目标端口没有打开,UDP 数据包的发送方将永远不会知道。** UDP 不提供接收方确认的方法。数据包被路由,如果它到达主机,则检查其正确性并成功接收或丢弃。send
写入 UDP 套接字时可能会返回错误代码的原因有很多,但它们都与接收主机的状态无关。** 我建议查阅sendto
联机帮助页了解可能的故障模式。
On the other hand, in the case of a TCP socket attempting to connect to an unopened port, the sender will never receive an acknowledgement of its initial connection request, and ultimately connect
will fail. At this point it would be up to the sender to stop sending data over the socket (as this will only generate more errors), but even in this case however, the socket file descriptor is never automatically closed.
另一方面,在 TCP 套接字尝试连接到未打开的端口的情况下,发送方将永远不会收到对其初始连接请求的确认,最终connect
将失败。此时应该由发送方停止通过套接字发送数据(因为这只会产生更多错误),但即使在这种情况下,套接字文件描述符也不会自动关闭。
** See response by @Zuljin in the comments.
** 请参阅@Zuljin 在评论中的回复。
回答by MarkR
The OS won't close your socket just because an error has happened. If the other end disappears, you can continue to send messages to it (but may receive further errors).
操作系统不会因为发生错误而关闭您的套接字。如果另一端消失,您可以继续向其发送消息(但可能会收到更多错误)。