Search code examples
c++linuxportnetstat

Find if a port is available to use in linux using c++


I am working on a C++ Project. To fulfill one of the requirement, I need to check if a port is available for using in my application anytime. To fulfill this , I have come to this following solution.

#include <iostream>
#include <cstdlib>
#include <stdexcept>
#include <string>
#include <stdio.h>


std::string _executeShellCommand(std::string command) {
    char buffer[256];
    std::string result = "";
    const char * cmd = command.c_str();
    FILE* pipe = popen(cmd, "r");
    if (!pipe) throw std::runtime_error("popen() failed!");

    try {
        while (!feof(pipe)) 
            if (fgets(buffer, 128, pipe) != NULL)
                result += buffer;
    } catch (...) {
        pclose(pipe);
        throw;
    }
    pclose(pipe);
    return result;
}

bool _isAvailablePort(unsigned short usPort){
    char shellCommand[256], pcPort[6];
    sprintf(shellCommand, "netstat -lntu | awk '{print $4}' | grep ':' | cut -d \":\" -f 2 | sort | uniq | grep %hu", usPort);
    sprintf(pcPort, "%hu", usPort);

    std::string output =  _executeShellCommand(std::string(shellCommand));

    if(output.find(std::string(pcPort)) != std::string::npos)
            return false;
    else
            return true;

}   


int main () {
    bool res = _isAvailablePort(5678);
    return 0;
}

Here Basically the _executeShellCommand function can excute any shell command anytime and can return the stdout output as return string.

And I am executing the following shell command in that function.

netstat -lntu | awk '{print $4}' | grep ':' | cut -d \":\" -f 2 | sort | uniq | grep portToCheck

So, if the port is already in use, the _executeShellCommand will return the PortValue itself, else it will return Blank. So, checking the returned string, I can decide.

So far so good.

Now, I want to be make my Project completely Crash-proof. So, before firing the netstat command, I want to make sure if it really exists or not. I want help in this case. I know, It's kind of stupid to doubt the availability of netstat command in a linux machine. I am just thinking of some user who removed netstat binary from his machine for some reason.

N.B. : I don't want make a bind() call to chack if the port is available or not. Also, it will be best if I can check if netstat command is available without calling _executeShellCommand for another time (i.e. without executing another Shell Command).


Solution

  • An even better idea is to make your code work completely without netstat altogether.

    On Linux, all that netstat does (for your use case) is read the contents of /proc/net/tcp, which enumerates all ports in use.

    All you have to do is open /proc/net/tcp yourself, and parse it. This becomes just an ordinary, boring, file parsing code. Can't get much more "crash-proof" than that.

    You will find the documentation of the format of /proc/net/tcp in Linux manual pages.

    In the unlikely event that you need to check UDP ports, this would be /proc/net/udp.

    Of course, there is a race window between the time you check /proc/net/tcp, where someone can grab the port. But that's also true with netstat as well, and since that's going to be a much slower process, this will actually be an improvement, and reduce the race window significantly.