Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 309
TheMeaningfulEngineer Avatar asked Jan 24 '15 21:01

TheMeaningfulEngineer


People also ask

Do UDP sockets need to be closed?

Close the socket Since there is no concept of a connection in UDP, there is no need to call shutdown.

How do UDP sockets work?

UDP is a very simple protocol. Messages, so called datagrams, are sent to other hosts on an IP network without the need to set up special transmission channels or data paths beforehand. The UDP socket only needs to be opened for communication. It listens for incoming messages and sends outgoing messages on request.

How do I bind a UDP socket to an IP address?

You would do this with the bind() function: int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); The first parameter is the file descriptor for the socket. The second is a pointer to a socket address structure which contains (for IPv4 or IPv6) the IP address and port to bind to.

Which socket is used in UDP?

int socket(int domain, int type, int protocol) Creates an unbound socket in the specified domain. Returns socket file descriptor. protocol – Protocol to be used by the socket. 0 means use default protocol for the address family.


2 Answers

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;
    }
like image 70
user590028 Avatar answered Sep 19 '22 10:09

user590028


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).

like image 44
Andrew Hacking Avatar answered Sep 20 '22 10:09

Andrew Hacking