使用Win32 API获取当前活动TCP/UDP连接端口对应进程信息

闲的蛋疼,写的小程序,首先感谢Sakura的帮助~
参考文献地址:GetTcpTable2的MSDN说明,其中的例子很详细,GetExtendedXXXTable虽然函数调用方式不一样但拿到的连接信息调用方式是一样的。
主要使用的API: GetTcpTable2和GetExtendedUdpTable(GetExtendedTcpTable)

#include
#include
#include
#include
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
typedef unsigned int uint;
typedef QMultimap INFOMAP;
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
bool GetProcessPort(INFOMAP& portmap)
{
	portmap.clear();
	PMIB_TCPTABLE2 pTcpTable;
	ULONG ulSize = 0;
	DWORD dwRetVal = 0;
	char szLocalAddr[128];
	char szRemoteAddr[128];
	struct in_addr IpAddr;
	int i;
	pTcpTable = (MIB_TCPTABLE2 *) MALLOC(sizeof (MIB_TCPTABLE2));
	if (pTcpTable == NULL) {
		status=("Error allocating memoryn");
		return false;
	}
	ulSize = sizeof (MIB_TCPTABLE);
	// Make an initial call to GetTcpTable2 to
	// get the necessary size into the ulSize variable
	if ((dwRetVal = GetTcpTable2(pTcpTable, &ulSize, TRUE)) ==
		ERROR_INSUFFICIENT_BUFFER) {
			FREE(pTcpTable);
			pTcpTable = (MIB_TCPTABLE2 *) MALLOC(ulSize);
			if (pTcpTable == NULL) {
				status=("Error allocating memoryn");
				return false;
			}
	}
	// Make a second call to GetTcpTable2 to get
	// the actual data we require
	if ((dwRetVal = GetTcpTable2(pTcpTable, &ulSize, TRUE)) == NO_ERROR) {
		printf("tNumber of entries: %dn", (int) pTcpTable->dwNumEntries);
		for (i = 0; i < (int) pTcpTable->dwNumEntries; i++) {
			uint portnum = ntohs((u_short)pTcpTable->table[i].dwLocalPort);
			uint pid = pTcpTable->table[i].dwOwningPid;
			portmap.insert(portnum,pid);
		}
	} else {
		status=QString("tGetTcpTable2 failed with %1n").arg(dwRetVal);
		FREE(pTcpTable);
		return false;
	}
	if (pTcpTable != NULL) {
		FREE(pTcpTable);
		pTcpTable = NULL;
	}
	MIB_UDPTABLE_OWNER_PID* pUdpTable;
	pUdpTable = (MIB_UDPTABLE_OWNER_PID *) MALLOC(sizeof (MIB_UDPTABLE_OWNER_PID));
	if (pUdpTable == NULL) {
		status=("Error allocating memoryn");
		return false;
	}
	ulSize = sizeof (MIB_UDPTABLE_OWNER_PID);
	if ((dwRetVal = GetExtendedUdpTable(pUdpTable, &ulSize, false,AF_INET,UDP_TABLE_OWNER_PID,0)) ==
		ERROR_INSUFFICIENT_BUFFER) {
			FREE(pUdpTable);
			pUdpTable = (MIB_UDPTABLE_OWNER_PID *) MALLOC(ulSize);
			if (pUdpTable == NULL) {
				status=("Error allocating memoryn");
				return false;
			}
	}
	if ((dwRetVal = GetExtendedUdpTable(pUdpTable, &ulSize, false,AF_INET,UDP_TABLE_OWNER_PID,0)) == NO_ERROR) {
		printf("tNumber of entries: %dn", (int) pUdpTable->dwNumEntries);
		for (i = 0; i < (int) pUdpTable->dwNumEntries; i++) {
			uint portnum = ntohs((u_short)pUdpTable->table[i].dwLocalPort);
			uint pid = pUdpTable->table[i].dwOwningPid;
			portmap.insert(portnum,pid);
		}
	} else {
		status=QString("tGetTcpTable2 failed with %1n").arg(dwRetVal);
		FREE(pUdpTable);
		return false;
	}
	if (pUdpTable != NULL) {
		FREE(pUdpTable);
		pUdpTable = NULL;
	}
	return true;
}

最终的进程pid<->端口信息存储在portmap这个multimap里面。(我用的QT做GUI,当然QMultimap可以换成其他任何map)
关于GetExtendedXXXTable需要注意的是,这个函数有不同的table参数可以传入,根据你想获得什么样的扩展信息,其他的和GetTcpTable2基本一致。

Leave a Reply

Your email address will not be published. Required fields are marked *