Reputation: 4083
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
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
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