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

Posted dvlinker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VC++获取系统TCPUDP端口使用信息,并判断端口是否被占用(附源码)相关的知识,希望对你有一定的参考价值。

       有时候我们需要判断某端口有没有被系统或者其他占用,代码该如何实现呢?其实很简单,我们可以调用系统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<TNetInfo*> vtPortInfoList;

	// 获取TCP连接表
	TNetInfo *ptNetInfo;
	for( s32 i=0 ; i<pTCPExTable->dwNumEntries ; 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++获取系统TCPUDP端口使用信息,并判断端口是否被占用(附源码)的主要内容,如果未能解决你的问题,请参考以下文章

VC++使用socket进行TCPUDP通信实例总结

socket开发调试工具TcpUdp推荐

python 自动获取端口信息和系统判断

TCPUDP的基本概念

36基于TCPUDP协议的嵌套字通信

多进程单线程多端口TCPUDP三层协议转发