TheMeaningfulEngineer
TheMeaningfulEngineer

Reputation: 16359

For UDP sockets, is the ip address unbounded the moment close() returns?

While reading this great answer i learned that a TCP socket can have a state called TIME_WAIT. Due to that state, it is possible that the TCP socket hasn't released the address it has been bonded to, even though the close(int fd) function returned 0.

Given that UDP is connectionless and it doesn't have reliability requirements to deliver the data like TCP, is it safe to assume that once the close(int fd) returns 0, the address is unbound?

Upvotes: 6

Views: 598

Answers (2)

Andrew Hacking
Andrew Hacking

Reputation: 6366

TL;DR: UDP sockets will be closed and unbound immediately (unless its a broadcast/multicast address with other listeners).

TIME WAIT is specified by the original RFC 793 and applies to TCP only. It requires a 2 * Maximum Segment Lifetime to expire before closing the socket in TCP.

The famous Unix Network Programming by Stevens also explains TCP's TIME WAIT in more detail for the curious.

UDP does not have connections.. TIME WAIT is not part of that protocol.

The Linux source whilst relevant for potentially proprietary behaviour on Linux based systems is not the authority on such matters.

The original 1981 DARPA TCP RFC 793 is authoritative as well as the Berkeley Sockets api on which POSIX sockets are based define the expected behaviour of the sockets API.

Also relevant is the 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 posted a role mid 2014 for an expert to help make Linux match or exceed the reliability and performance of the FreeBSD stack).

Upvotes: 1

user590028
user590028

Reputation: 11728

Yes, according to the source code 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() (~line 2028) flushes any pending frames, and releases the socket which frees the address.

You can demonstrate this with a simple example. You'll need netcat, a client and a server. One the server, run this code:

#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;
    }

Upvotes: 6

Related Questions