Search code examples
linuxsocketstcplsof

Outgoing TCP port matches listening port


I've encountered a weird happenstance where the results of my

lsof | grep 40006

produced

java      29722     appsrv   54u     IPv6           71135755        0t0      TCP localhost:40006->localhost:40006 (ESTABLISHED)

Generally I see

java      30916     appsrv   57u     IPv6           71143812        0t0      TCP localhost:43017->localhost:40006 (ESTABLISHED)

where the ports do not match on either side of the arrow. While lsof was producing the former result, I could not start an application which attempts to listen on the port 40006 even though the socket is configured as SO_REUSEADDR.

Can this happen? Should it?

uname gives: Linux femputer 2.6.32-24-server #39-Ubuntu SMP Wed Jul 28 06:21:40 UTC 2010 x86_64 GNU/Linux


Solution

  • It is possible to arrange such a connection by creating a socket, binding it to 127.0.0.1:40006, then connect() it to 127.0.0.1:40006. (Note: no listen()). I believe this is called an "active-active open".

    The following program demonstrates this:

    #include <stdio.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <unistd.h>
    
    int main()
    {
        int s;
        struct sockaddr_in sa = {
            .sin_family = PF_INET,
            .sin_port = htons(40006),
            .sin_addr.s_addr = htonl(INADDR_LOOPBACK) };
    
        s = socket(PF_INET, SOCK_STREAM, 0);
    
        if (s < 0) {
            perror("socket");
            return 1;
        }
    
        if (bind(s, (struct sockaddr *)&sa, sizeof sa) < 0) {
            perror("bind");
            return 1;
        }
    
        if (connect(s, (struct sockaddr *)&sa, sizeof sa) < 0) {
            perror("connect");
            return 1;
        }
    
        pause();
    
        return 0;
    }
    

    The reason that the port cannot be re-used is because the port is not listening - it is an outgoing port.