Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Linux handle multiple sockets bound to the same port with `INADDR_ANY` and a specific IP address?

Tags:

c

linux

tcp

sockets

I'm developing a server application on Linux and have a question about socket binding behavior when using INADDR_ANY and specific IP addresses. My test setup involves two sockets:

  1. One socket bound to port 80 with INADDR_ANY, meaning it listens on all available IP addresses.
  2. Another socket bound to port 80 on a specific IP address, 192.168.1.4.

My question is:

  1. If a client attempts to connect to 192.168.1.4 on port 80, is there any possibility that the connection could be handled by the socket bound to INADDR_ANY instead of the one explicitly bound to 192.168.1.4?

  2. I am also using the SO_REUSEPORT socket option on both sockets. Could this affect how the connections are routed, or is it purely related to allowing both sockets to bind to the same port without error?

Here is the relevant snippet of how I'm binding the sockets:

// Test Program //

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>

int main() {
    int sock1 = socket(AF_INET, SOCK_STREAM, 0);
    int sock2 = socket(AF_INET, SOCK_STREAM, 0);

    int optval = 1;
    setsockopt(sock1, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
    setsockopt(sock2, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));

    // Socket 1: Bind to INADDR_ANY (all interfaces)
    struct sockaddr_in addr1;
    addr1.sin_family = AF_INET;
    addr1.sin_addr.s_addr = htonl(INADDR_ANY);
    addr1.sin_port = htons(80);
    if (bind(sock1, (struct sockaddr*)&addr1, sizeof(addr1)) < 0) {
        perror("bind failed for sock1");
        exit(1);
    }

    // Socket 2: Bind to specific IP address
    struct sockaddr_in addr2;
    addr2.sin_family = AF_INET;
    addr2.sin_addr.s_addr = inet_addr("192.168.1.4");
    addr2.sin_port = htons(80);
    if (bind(sock2, (struct sockaddr*)&addr2, sizeof(addr2)) < 0) {
        perror("bind failed for sock2");
        exit(1);
    }

    int rval1 = listen(sock1, 5);
    if (rval1 == -1) {
        perror("listen failed for sock1");
        exit(1);
    }

    int rval2 = listen(sock2, 5);
    if (rval2 == -1) {
        perror("listen failed for sock2");
        exit(1);
    }

    printf("%s\n", "Exiting test program");
}

What I've Learned So Far:

  • The socket bound to INADDR_ANY listens on all available IPs, while the other socket only listens on 192.168.1.4.
  • The SO_REUSEPORT option allows both sockets to bind to the same port without errors, but as far as I understand, it doesn’t control which socket handles incoming connections.

My Key Questions:

  1. Is there any scenario where a connection targeting 192.168.1.4:80 could be handled by the INADDR_ANY socket?
  2. What role does SO_REUSEPORT play here? Does it impact which socket handles incoming connections, or is it only relevant during the binding process?

Desired Behavior:

I want to ensure that any connections targeting 192.168.1.4:80 are always handled by the second socket (the one explicitly bound to that address), and connections to other IPs (e.g., 127.0.0.1:80) are handled by the INADDR_ANY socket.

Any clarification or confirmation of how Linux handles this would be greatly appreciated!

like image 569
b.sullender Avatar asked Oct 16 '25 19:10

b.sullender


1 Answers

The SO_REUSEADDR option on TCP sockets only allows you to listen/bind a port if there's an outstanding connection from a prior run of the program that hasn't yet fully closed. It doesn't actually allow you to have multiple listening sockets open on the same IP/port.

The code above binds the sockets, but you haven't yet attempted to listen on either one. If you attempt to do so:

rval = listen(sock1, 5);
if (rval==-1) {
    perror("listen failed for sock1");
    exit(1);
}
rval = listen(sock2, 5);
if (rval==-1) {
    perror("listen failed for sock2");
    exit(1);
}

One of them will fail:

listen failed for sock2: Address already in use

You should only have one listening socket bound to INADDR_ANY, as that will handle any incoming connection on port 80, regardless of the interface.

like image 131
dbush Avatar answered Oct 18 '25 10:10

dbush