VC++获取系统TCP、UDP端口使用信息,并判断端口是否被占用(附源码)

VC++获取系统TCP、UDP端口使用信息,并判断端口是否被占用(附源码)_第1张图片

       有时候我们需要判断某端口有没有被系统或者其他占用,代码该如何实现呢?其实很简单,我们可以调用系统API函数GetExtendedTcpTable和GetExtendedUdpTable,分别获取TCP和UDP端口信息,其中的信息包括与端口关联的本端IP和远端IP,占用该端口的进程id等,对应的结构体如下所示:

typedef struct _MIB_TCPROW_OWNER_MODULE
{
    DWORD           dwState;
    DWORD           dwLocalAddr;
    DWORD           dwLocalPort;
    DWORD           dwRemoteAddr;
    DWORD           dwRemotePort;
    DWORD           dwOwningPid;
    LARGE_INTEGER   liCreateTimestamp;
    ULONGLONG       OwningModuleInfo[TCPIP_OWNING_MODULE_SIZE];
} MIB_TCPROW_OWNER_MODULE, *PMIB_TCPROW_OWNER_MODULE;

      光有进程id,无法直观地看到端口被哪个程序占用了,当然我们可以通过进程id到任务管理器中去查找。通过进程的id,我们可以获取系统进程快照,得到对应的进程名称,代码如下:

BOOL GetProcessNameById( u32 ProcessId,TCHAR ProcessName[MAX_PATH] )
{
	HANDLE hProcessSnap;
	PROCESSENTRY32 pe32;

	// 快照系统所有进程
	hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );// 第二个参数无效
	if( hProcessSnap == INVALID_HANDLE_VALUE )
	{
		return FALSE;
	}

	// 结构体大小一定要填充。
	pe32.dwSize = sizeof( PROCESSENTRY32 );

	// 获取第一个进程信息
	if( !Process32First( hProcessSnap, &pe32 ) )
	{
		CloseHandle( hProcessSnap );          // clean the snapshot object
		return FALSE;
	}

	// 遍历所有进程
	do
	{
		if( pe32.th32ProcessID==ProcessId ) 
		{
			lstrcpy( ProcessName, pe32.szExeFile );
            CloseHandle(hProcessSnap );
			return TRUE;
		}
	} while( Process32Next( hProcessSnap, &pe32 ) );


	CloseHandle(hProcessSnap );
    return FALSE;
}

          判断端口是否被占用的接口CheckPortUsed封装如下:(代码中还保存了端口的详细信息)

// 端口的详细信息
typedef struct tagTNetInfo
{
	emPortType  bySockType; // TCP、UDP
	DWORD dwLocalIP;     // 网络序
	DWORD dwRemoteIP;    // 网络序
	DWORD dwLocalPort;   // 网络序
	DWORD dwRemotePort;  // 网络序
	DWORD dwPID;
	TCHAR szProcessName[MAX_PATH];
}TNetInfo;


BOOL CheckPortUsed( int nPort )
{
	// 1、获取TCP连接及端口信息
	// 第一次调用时不知道要传入的缓冲区大小,所以要试探一下,参数dwTcpCount会返回实际大小
	PMIB_TCPTABLE_OWNER_MODULE pTCPExTable = new MIB_TCPTABLE_OWNER_MODULE;
	DWORD dwTcpCount = sizeof(MIB_UDPTABLE_OWNER_MODULE);
	if ( GetExtendedTcpTable( pTCPExTable, &dwTcpCount, TRUE, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0 ) == ERROR_INSUFFICIENT_BUFFER )
	{
		pTCPExTable = (MIB_TCPTABLE_OWNER_MODULE *)new char[dwTcpCount];
	}
	DWORD dwRet= GetExtendedTcpTable( pTCPExTable, &dwTcpCount, TRUE, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0 );
	if( dwRet ) 
	{
		return ;
	}

	// 1、获取UDP连接及端口信息
	PMIB_UDPTABLE_OWNER_MODULE pUDPExTable = new MIB_UDPTABLE_OWNER_MODULE;
	DWORD dwUdpCount = sizeof(MIB_TCPTABLE_OWNER_MODULE);
	if ( GetExtendedUdpTable( pUDPExTable, &dwUdpCount, TRUE, AF_INET, UDP_TABLE_OWNER_MODULE, 0 ) == ERROR_INSUFFICIENT_BUFFER )
	{
		pUDPExTable = (MIB_UDPTABLE_OWNER_MODULE *)new char[dwUdpCount];
	}
	dwRet = GetExtendedUdpTable( pUDPExTable, &dwUdpCount, TRUE, AF_INET, UDP_TABLE_OWNER_MODULE, 0 );
	if( dwRet ) 
	{
		return ;
	}

	TCHAR szProcessName[MAX_PATH]    = {0};

	vector vtPortInfoList;

	// 获取TCP连接表
	TNetInfo *ptNetInfo;
	for( s32 i=0 ; idwNumEntries ; i++ ) 
	{
		ptNetInfo = new TNetInfo;

		// 通过进程id获取进程名
		GetProcessNameById( hProcessSnap, pTCPExTable->table[i].dwOwningPid, szProcessName );

		ptNetInfo->bySockType  = emTCP;
		ptNetInfo->dwLocalIP   = pTCPExTable->table[i].dwLocalAddr;
		ptNetInfo->dwLocalPort = htons( pTCPExTable->table[i].dwLocalPort );
		ptNetInfo->dwRemoteIP  = pTCPExTable->table[i].dwRemoteAddr;
		ptNetInfo->dwRemotePort= htons( pTCPExTable->table[i].dwRemotePort );
		ptNetInfo->dwPID       = pTCPExTable->table[i].dwOwningPid;
		lstrcpy(ptNetInfo->szProcessName, szProcessName);

		vtPortInfoList.push_back( ptNetInfo );
	}

	// 获取UDP连接表
	for( s32 i = 0; i < pUDPExTable->dwNumEntries; i++ ) 
	{
		ptNetInfo = new TNetInfo;

		//PID转换为进程名
		GetProcessNameById( pUDPExTable->table[i].dwOwningPid, szProcessName );

		ptNetInfo->bySockType  = emUDP;
		ptNetInfo->dwLocalIP   = pUDPExTable->table[i].dwLocalAddr;
		ptNetInfo->dwLocalPort = htons( pUDPExTable->table[i].dwLocalPort );
		ptNetInfo->dwPID       = pUDPExTable->table[i].dwOwningPid;
		ptNetInfo->szProcessName = szProcessName;

		vtPortInfoList.push_back( ptNetInfo );
	}

	DWORD dwNetPort = ntohl( nPort );
	for ( int i = 0; i < vtPortInfoList.size(); i++ )
	{
		if ( dwNetPort == vtPortInfoList[i].dwLocalPort )
		{
			return TRUE;
		}
	}

	return FALSE;
}

你可能感兴趣的:(VC++常用功能代码封装,端口,UdpTable,TcpTable,占用)