C语言 对于 UDP 套接字,当 close() 返回的时刻,IP 地址是否不受限制



在阅读这个伟大的答案时,我了解到TCP套接字可以具有称为TIME_WAIT的状态。由于这种状态,TCP 套接字可能尚未释放它绑定到的地址,即使 close(int fd) 函数返回0

鉴于 UDP 是无连接的,并且它没有像 TCP 那样传递数据的可靠性要求,是否可以安全地假设一旦close(int fd)返回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} 60000nn");
    printf("type: hello world<enter>n");
    printf("Hit enter when you've done this...");
    getchar();
    printf("nNow check the input queue on this servern");
    printf("    netstat -an|grep 60000n");
    printf("Notice that we have buffered data we have not readn");
    printf("(probably about 360 bytes)n");
    printf("Hit enter to continue...");
    getchar();
    printf("nI'm going to end. After I do, run netstat -an againn");
    printf("and you'll notice port 60000 is gone.nn");
    printf("Re-run this program on server again and see youn");
    printf("have no problem re-acquiring the UDP port.n");
    return 0;
    }

TL;DR:UDP 套接字将立即关闭并解除绑定(除非它是与其他侦听器的广播/组播地址)。

TIME WAIT 由原始 RFC 793 指定,仅适用于 TCP。它要求在关闭 TCP 中的套接字之前,2 * 最大段生存期到期。

Stevens著名的Unix网络编程也为好奇的人更详细地解释了TCP的TIME WAIT。

UDP 没有连接。.TIME WAIT 不是该协议的一部分。

Linux

源代码虽然与基于Linux的系统上的潜在专有行为相关,但并不是此类问题的权威。

最初的1981年DARPA TCP RFC 793是权威的,POSIX套接字所基于的Berkeley Sockets API定义了套接字API的预期行为。

同样相关的是BSD网络堆栈,它为早期互联网中的TCP/IP到今天的Windows,iOS和OSX提供支持,并提供TCP/IP RFC的权威参考实现。 BSD堆栈仍然被视为几年后未来Linux堆栈的基准。(Facebook 在 2014 年年中发布了一个专家职位,帮助 Linux 达到或超过FreeBSD堆栈的可靠性和性能)。

最新更新