how do I find in C that a port is free to use?

后端 未结 3 1762
长情又很酷
长情又很酷 2021-02-14 02:19

The OS is Linux. I have a server process that can change its port realtime. However I would like to know in advance if a port is free before binding.

Scenario: Server bi

相关标签:
3条回答
  • 2021-02-14 03:00

    If your server was told what port to use, just bind() it. Seriously.

    Sure, you could parse /proc/net/tcp and see if the port's in use. But then what? You still need to call bind() now that you know your port is free, and it'll tell you if the port was free then anyway, and so there was no point in groveling through /proc/net/tcp and doing all that (slow!) string production and parsing and extra kernel trips through not-very-well-optimized (read: super slow compared to bind()) diagnostic paths, just to get information that could well be out of date before you even finished parsing it. So just call bind() and be happy.

    0 讨论(0)
  • 2021-02-14 03:15

    I struggled with this myself and have slightly modified your code.

    The solution is to set serv_addr.sin_port = 0 (auto assign port).

    Note In the bind() and the getsockname() lines there are unclean casts from sockaddr_in to sockaddr. I have seen it done many places and I'm looking for a safer solution.

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    
    // ... snip ...
    
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock < 0) {
        printf("socket error\n");
        return;
    }
    printf("Opened %d\n", sock);
    
    struct sockaddr_in serv_addr;
    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = 0;
    if (bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
        if(errno == EADDRINUSE) {
            printf("the port is not available. already to other process\n");
            return;
        } else {
            printf("could not bind to process (%d) %s\n", errno, strerror(errno));
            return;
        }
    }
    
    socklen_t len = sizeof(serv_addr);
    if (getsockname(sock, (struct sockaddr *)&serv_addr, &len) == -1) {
        perror("getsockname");
        return;
    }
    
    printf("port number %d\n", ntohs(serv_addr.sin_port));
    
    
    if (close (sock) < 0 ) {
        printf("did not close: %s\n", strerror(errno));
        return;
    }
    

    Program output

    Opened 4
    port number 59081
    
    0 讨论(0)
  • 2021-02-14 03:17

    This is an obvious race condition, since other processes on your system might be binding to ports in parallel. So, any solution you find will be imperfect, and you will still need to just write it according to the "try to bind(), if it fails pick a new port number and try again" approach.

    0 讨论(0)
提交回复
热议问题