如何确定客户端是否连接到我的套接字?

问题描述:

我有调用打开TCP服务器套接字的库(本例中为gstreamer)的代码。我有端口号,但我无法访问文件描述符。如何确定客户端是否连接到我的套接字?

我想从我的应用程序检测是否有客户端当前连接到此端口。理想情况下,我想要一个跨平台的方法(Linux + Mac,* BSD的加分)。

我知道netstat可以帮助我做到这一点,但我想要一个编程技术。

+0

在Linux上,您可以从'/ proc/net/tcp'中读取。 – Sergio

+0

为什么不能获取'netstat'的源代码并查看它是如何完成的? – KevinDTimm

+0

如果你不能通过图书馆本身,它似乎是一个坏主意。我相信gstreamer运行它自己的线程,所以当你检查并获得响应(0连接)时,你可能实际上有一个新的连接。 – viraptor

库代码在进程的地址空间中运行。它使用的文件描述符只是int值,您可以使用getsockopt()查找TCP/IP套接字,然后在那些套接字上使用getpeername()来查找连接的套接字。按照POSIX文件for getsockopt()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; 
    } 
} 

这会发现所有连接的TCP套接字的过程中有在检查的时候打开,它应该是相当便携。

+0

嗯......我无法完全解析manpage:getpeername'会告诉我客户端是否连接到我的套接字? – Yoric

+0

@Yoric'getpeername()'的全部目的是告诉你*谁连接到套接字的另一端。这样做,它会告诉你*如果它已连接。 –

扩大Serhio。如果打开的/ proc //网/ TCP和阅读它,你会看到:

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

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

因此,分析出这些行(跳跃第一行然后sscanf)并从local_address字段中提取端口号以查找您感兴趣的端口。查看st字段以查找处于连接状态的套接字。如果在连接状态下发现任何内容,则返回true。