如何使用Windows C++ API获取应用程序的监听端口
Windows下获取指定应用监听端口的API及实现方案
核心依赖API
Windows官方提供的IP Helper库中,GetExtendedTcpTable、GetExtendedUdpTable两个API是实现进程与端口关联查询的核心,需引入头文件iphlpapi.h,编译时链接iphlpapi.lib。
这两个API返回的系统TCP/UDP连接表中,每个条目都包含对应连接/监听端口绑定的进程ID(PID),匹配目标应用的PID即可提取到对应的端口信息。
具体实现步骤
- 第一步:获取目标应用的PID
可通过CreateToolhelp32SnapshotAPI枚举系统进程,匹配目标应用的进程名获取对应PID,也可以直接传入用户指定的PID。 - 第二步:获取TCP端口关联表
调用GetExtendedTcpTable,传入TCP_TABLE_OWNER_PID_LISTENER参数专门获取监听状态的TCP端口关联信息,可通过AF_INET/AF_INET6参数区分IPv4/IPv6协议。 - 第三步:获取UDP端口关联表
调用GetExtendedUdpTable,传入UDP_TABLE_OWNER_PID参数获取所有UDP端口的关联信息。 - 第四步:匹配PID提取端口
遍历TCP、UDP端口关联表的所有条目,匹配目标应用的PID,提取对应的端口号即可。
C语言实现示例
#include <windows.h> #include <iphlpapi.h> #include <tlhelp32.h> #include <stdio.h> #include <winsock.h> #pragma comment(lib, "iphlpapi.lib") #pragma comment(lib, "advapi32.lib") #pragma comment(lib, "ws2_32.lib") // 根据进程名获取对应PID DWORD GetPidByProcessName(const WCHAR* processName) { PROCESSENTRY32 pe32; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot == INVALID_HANDLE_VALUE) return 0; pe32.dwSize = sizeof(PROCESSENTRY32); if (!Process32First(hSnapshot, &pe32)) { CloseHandle(hSnapshot); return 0; } do { if (_wcsicmp(pe32.szExeFile, processName) == 0) { CloseHandle(hSnapshot); return pe32.th32ProcessID; } } while (Process32Next(hSnapshot, &pe32)); CloseHandle(hSnapshot); return 0; } // 打印目标PID对应的TCP监听端口 void ListTcpListenPortsByPid(DWORD targetPid) { PMIB_TCPTABLE_OWNER_PID pTcpTable = NULL; DWORD dwSize = 0; // 首次调用获取所需缓冲区大小 if (GetExtendedTcpTable(NULL, &dwSize, FALSE, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0) == ERROR_INSUFFICIENT_BUFFER) { pTcpTable = (PMIB_TCPTABLE_OWNER_PID)HeapAlloc(GetProcessHeap(), 0, dwSize); if (pTcpTable == NULL) return; } else return; // 二次调用获取实际端口数据 if (GetExtendedTcpTable(pTcpTable, &dwSize, FALSE, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0) == NO_ERROR) { for (DWORD i = 0; i < pTcpTable->dwNumEntries; i++) { if (pTcpTable->table[i].dwOwningPid == targetPid) { printf("TCP监听端口:%d\n", ntohs((u_short)pTcpTable->table[i].dwLocalPort)); } } } HeapFree(GetProcessHeap(), 0, pTcpTable); } int main() { // 示例:查询chrome.exe的监听端口,替换为你的目标进程名即可 DWORD targetPid = GetPidByProcessName(L"chrome.exe"); if (targetPid == 0) { printf("未找到目标进程\n"); return 1; } printf("目标进程PID:%d\n", targetPid); ListTcpListenPortsByPid(targetPid); // UDP端口查询逻辑与TCP类似,调用GetExtendedUdpTable即可实现 return 0; }
注意事项
- 示例仅实现了IPv4下的TCP监听端口查询,如需IPv6支持,将
AF_INET替换为AF_INET6,对应表结构替换为MIB_TCP6TABLE_OWNER_PID即可。 - 如需查询已建立连接的端口而非监听端口,将
TCP_TABLE_OWNER_PID_LISTENER替换为TCP_TABLE_OWNER_PID_CONNECTIONS即可。 - 临时排查无需代码实现的场景,可直接在cmd中执行
netstat -ano | findstr 目标PID,快速查询对应端口。 - 拿到目标端口后,可在Wireshark中通过
tcp.port == 目标端口/udp.port == 目标端口过滤规则筛选对应应用的数据包,也可在Scapy中通过端口匹配过滤流量。
内容的提问来源于stack exchange,提问作者yellow up
相关产品推荐
相关产品推荐

