Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
622 views
in Technique[技术] by (71.8m points)

winapi - Getting PID of peer socket on Windows

I am writing a web proxy and when a request comes in (typically from the browser on the machine), I'd like to also get the pid and any other requesting application. Is there any way to determine this using Win32?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

What you are asking for is only possible if the client and server are running on the same machine.

When a client is connected to the proxy, the proxy can use getpeername() to query the socket for the remote client IP/Port (or use the IP/Port reported by accept()) and getsockname() to get its local server IP/Port. Then the proxy can use GetTcpTable2() (IPv4) or GetTcp6Table2() (IPv6) to retrieve a list of active TCP connections and loop through it looking for a connection that matches the IP/Port pairs. If found, the list entry will tell you the process ID that owns that connection.

For example:

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);
    ...
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...