对于 UDP 套接字,IP 地址是否在 close() returns 时刻不受限制?
For UDP sockets, is the ip address unbounded the moment close() returns?
在阅读 this great answer 时,我了解到 TCP 套接字可以具有称为 TIME_WAIT
的状态。由于该状态,即使 close(int fd)
函数返回 0
.
,TCP 套接字可能还没有释放它所绑定的地址。
鉴于 UDP 是无连接的,并且它没有像 TCP 那样传送数据的可靠性要求,可以安全地假设一旦 close(int fd)
returns 0
,地址未绑定?
是的,根据源代码 https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/udp.c?id=refs/tags/v3.19-rc6,udp_destroy_sock()
(~第 2028 行)刷新所有挂起的帧,并释放释放地址的套接字。
您可以用一个简单的例子来证明这一点。您将需要 netcat
、一个客户端和一个服务器。服务器之一,运行 这个代码:
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
int main() {
struct sockaddr_in me;
int sock;
if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
perror("socket error:");
return -1;
}
memset(&me, 0, sizeof(me));
me.sin_family = AF_INET;
me.sin_port = htons(60000);
me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock, (struct sockaddr*)&me, sizeof(me)) == -1) {
perror("bind error: ");
return -1;
}
printf("On client execute:\n");
printf(" nc -u {servers ip address} 60000\n\n");
printf("type: hello world<enter>\n");
printf("Hit enter when you've done this...");
getchar();
printf("\nNow check the input queue on this server\n");
printf(" netstat -an|grep 60000\n");
printf("Notice that we have buffered data we have not read\n");
printf("(probably about 360 bytes)\n");
printf("Hit enter to continue...");
getchar();
printf("\nI'm going to end. After I do, run netstat -an again\n");
printf("and you'll notice port 60000 is gone.\n\n");
printf("Re-run this program on server again and see you\n");
printf("have no problem re-acquiring the UDP port.\n");
return 0;
}
TL;DR: UDP 套接字将立即关闭并解除绑定(除非它是与其他侦听器的 broadcast/multicast 地址)。
TIME WAIT 由原RFC 793指定,仅适用于TCP。在关闭 TCP 套接字之前,它需要 2 * 最大段生命周期到期。
Stevens 的著名 Unix Network Programming 也为好奇的人更详细地解释了 TCP 的 TIME WAIT。
UDP 没有连接。TIME WAIT 不是该协议的一部分。
Linux 来源虽然与基于 Linux 的系统上的潜在专有行为相关,但不是此类问题的权威。
最初的 1981 DARPA TCP RFC 793 和 Berkeley Sockets api 一样具有权威性 POSIX套接字 基于定义套接字API.
的预期行为
同样相关的是 BSD network stack which powered TCP/IP in the early internet through to Windows, iOS, and OSX today and provides the authoritative reference implementation of the TCP/IP RFCs. The BSD stack is still regarded as the benchmark for a future Linux stack several years from now.(Facebook 在 2014 年年中发布了一个专家角色,帮助 Linux 达到或超过 FreeBSD 堆栈的可靠性和性能)。
在阅读 this great answer 时,我了解到 TCP 套接字可以具有称为 TIME_WAIT
的状态。由于该状态,即使 close(int fd)
函数返回 0
.
鉴于 UDP 是无连接的,并且它没有像 TCP 那样传送数据的可靠性要求,可以安全地假设一旦 close(int fd)
returns 0
,地址未绑定?
是的,根据源代码 https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/udp.c?id=refs/tags/v3.19-rc6,udp_destroy_sock()
(~第 2028 行)刷新所有挂起的帧,并释放释放地址的套接字。
您可以用一个简单的例子来证明这一点。您将需要 netcat
、一个客户端和一个服务器。服务器之一,运行 这个代码:
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
int main() {
struct sockaddr_in me;
int sock;
if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
perror("socket error:");
return -1;
}
memset(&me, 0, sizeof(me));
me.sin_family = AF_INET;
me.sin_port = htons(60000);
me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock, (struct sockaddr*)&me, sizeof(me)) == -1) {
perror("bind error: ");
return -1;
}
printf("On client execute:\n");
printf(" nc -u {servers ip address} 60000\n\n");
printf("type: hello world<enter>\n");
printf("Hit enter when you've done this...");
getchar();
printf("\nNow check the input queue on this server\n");
printf(" netstat -an|grep 60000\n");
printf("Notice that we have buffered data we have not read\n");
printf("(probably about 360 bytes)\n");
printf("Hit enter to continue...");
getchar();
printf("\nI'm going to end. After I do, run netstat -an again\n");
printf("and you'll notice port 60000 is gone.\n\n");
printf("Re-run this program on server again and see you\n");
printf("have no problem re-acquiring the UDP port.\n");
return 0;
}
TL;DR: UDP 套接字将立即关闭并解除绑定(除非它是与其他侦听器的 broadcast/multicast 地址)。
TIME WAIT 由原RFC 793指定,仅适用于TCP。在关闭 TCP 套接字之前,它需要 2 * 最大段生命周期到期。
Stevens 的著名 Unix Network Programming 也为好奇的人更详细地解释了 TCP 的 TIME WAIT。
UDP 没有连接。TIME WAIT 不是该协议的一部分。
Linux 来源虽然与基于 Linux 的系统上的潜在专有行为相关,但不是此类问题的权威。
最初的 1981 DARPA TCP RFC 793 和 Berkeley Sockets api 一样具有权威性 POSIX套接字 基于定义套接字API.
的预期行为同样相关的是 BSD network stack which powered TCP/IP in the early internet through to Windows, iOS, and OSX today and provides the authoritative reference implementation of the TCP/IP RFCs. The BSD stack is still regarded as the benchmark for a future Linux stack several years from now.(Facebook 在 2014 年年中发布了一个专家角色,帮助 Linux 达到或超过 FreeBSD 堆栈的可靠性和性能)。