3

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

Surajeet Bharati
  • 1,363
  • 1
  • 18
  • 36
  • There are more commands you can use like `whereis netstat` or so, and check the output. – πάντα ῥεῖ Sep 21 '16 at 13:07
  • Note that you'll have to handle the case where the port becomes unavailable between your check and the time you use it. Depending on the context, checking that it is available is then useless or it can be better to take the ownership of the port at the time you want to check (and release if it is finally not used). – AProgrammer Sep 21 '16 at 13:32
  • Is there a specific reason why not to use `bind()`? – karastojko Sep 21 '16 at 15:01
  • @karastojko, basically I will be opening a Tcl Comm Server on that port by firing a Tcl command (using `Tcl_Eval`) after checking the port's availability. So, I don't want to bind the port, as I have to close immediately after binding. – Surajeet Bharati Sep 22 '16 at 09:36
  • @AProgrammer, that case has been welly handle. I have used some concepts of `critical section` and `mutex`. – Surajeet Bharati Sep 22 '16 at 09:40
  • @πάνταῥεῖ, I was thinking of not firing another shell command. Anyways, thanks for your input. – Surajeet Bharati Sep 22 '16 at 09:41

2 Answers2

4

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.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
0

Since you're asking for a way to check if netstat command is available, I won't try to suggest the other ways in C++. The shell way is checking return code of the following command:

command -v netstat

If netstat binary is available in $PATH, then the command returns 0. In Bash it usually looks like this:

command -v netstat
if [ $? -eq 0 ]; then
  netstat # ...
else
  echo >&2 "Error: netstat is not available"
fi

Or simply

command -v netstat >/dev/null && netstat # ...
Ruslan Osmanov
  • 20,486
  • 7
  • 46
  • 60