在 Windows 上获取对等套接字的 PID

Posted

技术标签:

【中文标题】在 Windows 上获取对等套接字的 PID【英文标题】:Getting PID of peer socket on Windows 【发布时间】:2014-08-21 15:10:06 【问题描述】:

我正在编写一个网络代理,当一个请求进入时(通常来自机器上的浏览器),我还想获取 pid 和任何其他请求应用程序。 有没有办法使用 Win32 来确定这一点?

【问题讨论】:

Fiddler 提供了发起请求的进程的详细信息。因此应该有一些方法可以做到这一点。 【参考方案1】:

只有当客户端和服务器在同一台机器上运行时,您的要求才可能实现。

当客户端连接到proxy时,proxy可以使用getpeername()查询socket的远程客户端IP/Port(或使用accept()报告的IP/Port)和getsockname()获取其本地服务器 IP/端口。然后代理可以使用GetTcpTable2() (IPv4) 或GetTcp6Table2() (IPv6) 来检索活动 TCP 连接列表并循环通过它寻找与 IP/端口对匹配的连接。如果找到,列表条目将告诉您拥有该连接的进程 ID。

例如:

DWORD GetClientPid(SOCKET client)

    DWORD pid = 0;

    sockaddr_in ServerAddr = 0;
    int ServerAddrSize = sizeof(ServerAddr);

    sockaddr_in ClientAddr = 0;
    int ClientAddrSize = sizeof(ClientAddr);

    if ((getsockname(client, (sockaddr*)&ServerAddr, &ServerAddrSize) == 0) &&
        (getpeername(client, (sockaddr*)&ClientAddr, &ClientAddrSize) == 0))
    
        PMIB_TCPTABLE2 TcpTable = NULL;
        ULONG TcpTableSize = 0;
        ULONG result;

        do
        
            result = GetTcpTable2(TcpTable, &TcpTableSize, TRUE);
            if (result != ERROR_INSUFFICIENT_BUFFER)
                break;

            LocalFree(TcpTable);
            TcpTable = (PMIB_TCPTABLE2) LocalAlloc(LMEM_FIXED, TcpTableSize);
        
        while (TcpTable != NULL);

        if (result == NO_ERROR)
        
            for (DWORD dw = 0; dw < TcpTable->dwNumEntries; ++dw)
            
                PMIB_TCPROW2 row = &(TcpTable->table[dw]);

                if ((row->dwState == MIB_TCP_STATE_ESTAB) &&
                    (row->dwLocalAddr == ClientAddr.sin_addr.s_addr) &&
                    ((row->dwLocalPort & 0xFFFF) == ClientAddr.sin_port) &&
                    (row->dwRemoteAddr == ServerAddr.sin_addr.s_addr) &&
                    ((row->dwRemotePort & 0xFFFF) == ServerAddr.sin_port))
                
                    pid = row->dwOwningPid;
                    break;
                
            
        

        LocalFree(TcpTable);
    

    return pid;

SOCKET client = accept(server, NULL, NULL);
if (client != INVALID_SOCKET)

    DWORD ClientPid = GetClientPid(client);
    ...

【讨论】:

感谢您的回答,这很有帮助。我也很感兴趣,为什么在 dwLocalPort 的 32 个 DWORD 位中 row-&gt;dwLocalPort &amp; 0xFFFF 中有 16 位被屏蔽?是不是因为端口只能从 0 到 65536-1,而我们不需要这些位,并且它以某种方式为我们提供了更好的性能?不确定该位掩码是否更改了任何内容。谢谢。 根据MIB_TCPROW2 documentation: "IP 端口号的最大大小为 16 位,因此只能使用低 16 位。高 16 位可能包含未初始化的data." 掩码用于强制将高位清零,因此任何未初始化的数据都不会影响比较。

以上是关于在 Windows 上获取对等套接字的 PID的主要内容,如果未能解决你的问题,请参考以下文章

在Python中,当在localhost上接受TCP套接字连接时,无法获得正确的对等体IP地址。

C++ 中的 Bittorrent 客户端,在非阻塞套接字上连接到对等点总是超时

如何控制对等端的套接字[TCP打孔]

java.net.socketexception 连接重置由对等套接字写入错误通过 Jenkins 在 Tomcat7 上部署战争时(使用 Maven)

浏览器上的 GCDAsyncSocket 立即连接和断开连接,并出现“远程对等方关闭套接字”错误

Windows 上是不是有 Unix 域套接字模拟?