c++boostportlisten

Using C++ and Boost (or not?) to check if a specific port is being used?


I am trying to check if a specific port is being used in C++. I am not trying to have the C++ program listen on that port for any reason, just check to see if it is being used. There will be another program listening on that port, and if it stops, I want my program to do something. So, it will check every 10 seconds or so, and if the port is in use, it will do nothing, but if the port becomes available, something will happen.

I've been looking at the boost ASIO library, but I can't seem to figure out how to accomplish this.


Solution

  • There's two options here.

    If you actually want to check the port is use, simply attempt a bind:

    bool port_in_use(unsigned short port) {
        using namespace boost::asio;
        using ip::tcp;
    
        io_service svc;
        tcp::acceptor a(svc);
    
        boost::system::error_code ec;
        a.open(tcp::v4(), ec) || a.bind({ tcp::v4(), port }, ec);
    
        return ec == error::address_in_use;
    }
    

    See it live: Live On Coliru, correctly printing

    Port 1078 is in use
    

    CAVEAT there could be other reasons why you can't bind to a local endpoint; check that you have the required permissions first (the permission error is being swallowed here)

    If you actually want to check that connections are being accepted, you will have to make a connection. This could be somewhat more time consuming so you might want to run this under a timeout:

    bool accepting_connections(unsigned short port) {
        using namespace boost::asio;
        using ip::tcp;
        using ec = boost::system::error_code;
    
        bool result = false;
    
        try
        {
            io_service svc;
            tcp::socket s(svc);
            deadline_timer tim(svc, boost::posix_time::seconds(1));
    
            tim.async_wait([&](ec) { s.cancel(); });
            s.async_connect({{}, port}, [&](ec ec) {
                    result = !ec; 
                });
    
            svc.run();
        } catch(...) { }
    
        return result;
    }
    

    Test:

    int main() {
        using namespace std;
    
        if (accepting_connections(22))
            cout << "Port 22 is accepting connections\n";
    }