Yoric
Yoric

Reputation: 4083

How can I determine if clients are connected to my socket?

I have code that calls a library (gstreamer, in this case) that opens a TCP server socket. I have the port number but I do not have access to the file descriptor.

I'd like to detect from my app whether there are clients currently connected to this port. Ideally, I'd like a cross-platform approach (Linux + Mac, bonus points for *BSD).

I know that netstat could help me do that, but I'd like a programmatic technique.

Upvotes: 3

Views: 972

Answers (2)

Andrew Henle
Andrew Henle

Reputation: 1

The library code runs in your process's address space. The file descriptor(s) it uses are just int values that you can use getsockopt() on to find TCP/IP sockets, then getpeername() on those sockets to find connected ones. Per the POSIX documentation for getsockopt() and getpeername():

#include <sys/socket.h>

// probably better to use getrlimit() here...
#define MAX_FD 1024

int tcp_socket_fds[ MAX_FD ];
struct sockaddr_in peers[ MAX_FD ];

for ( int fd = 0; fd < MAX_FD; fd++ )
{
    int type;
    int len = sizeof( type );

    int rc = getsockopt( fd, SOL_SOCKET, SO_TYPE, &type, &len );    
    if ( ( 0 == rc ) && ( SOCK_STREAM == type ) )
    {
        tcp_socket_fds[ fd ] = 1;

        socklen_t socket_len = sizeof( peers[ fd ] );
        rc = getpeername( fd, &( peers[ fd ] ), &socket_len );

        // zero out the peer if getpeername() failed
        if ( 0 != rc )
        {
            memset( &( peers[ fd ], 0, sizeof( peers[ fd ] ) );
        }
    }
    else
    {
        tcp_socket_fds[ fd ] = 0;
    }
}

That will find all connected TCP sockets your process has open at the time of the check, and it should be fairly portable.

Upvotes: 1

evaitl
evaitl

Reputation: 1395

Expanding on Serhio. If you open /proc//net/tcp and read it, you'll see:

 sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode                                                     
   0: 0100007F:0CEA 00000000:0000 0A 00000000:00000000 00:00000000 00000000   116        0 14581 1 ffff880406690000 100 0 0 10 0                     
   1: 00000000:008B 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 15646 1 ffff880404aa8700 100 0 0 10 0                     
   2: 0100007F:13AD 00000000:0000 0A 00000000:00000000 00:00000000 00000000  1000        0 16859998 1 ffff880406692a00 100 0 0 10 0                  
   3: 0100007F:F76E 00000000:0000 0A 00000000:00000000 00:00000000 00000000  1000        0 31381008 1 ffff8800d7926200 100 0 0 10 0  
...

From the proc manpage:

 /proc/net/tcp
              Holds a dump of the TCP socket table.  Much of the information
              is not of use apart from debugging.  The "sl" value is the
              kernel hash slot for the socket, the "local_address" is the
              local address and port number pair.  The "rem_address" is the
              remote address and port number pair (if connected).  "St" is
              the internal status of the socket.  The "tx_queue" and
              "rx_queue" are the outgoing and incoming data queue in terms
              of kernel memory usage.  The "tr", "tm->when", and "rexmits"
              fields hold internal information of the kernel socket state
              and are useful only for debugging.  The "uid" field holds the
              effective UID of the creator of the socket.

So, parse out these lines (skip first line then sscanf) and extract the port numbers from the local_address field to find the port you are interested in. Look at the st field to find sockets in the connected state. If you find anything in the connected state, return true.

Upvotes: 0

Related Questions