使用Win32 API获得端口占用列表并关闭对应进程

获得端口占用可以用命令netstat -ab实现,结束进程可以用taskkill,但是用C++怎么实现呢?

答案是Windows已经提供了API实现功能。GetTcpTable可以得到当前占用的端口数量以及具体的ip和端口,但是得不到对应的进程。GetTcpTable2可以额外获得占用端口对应进程的pid,拿到pid,后面问题就好办了。

下面是效果图:
使用Win32 API获得端口占用列表并关闭对应进程_第1张图片

源码:

#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include 
#include 

#include 
#include //GetModuleFileNameEx

#include 
#pragma comment(lib, "iphlpapi.lib")

#include 
#pragma comment(lib, "ws2_32.lib")

using namespace std;

DWORD GetIdOfOccupiedPortProcess(unsigned short port)
{
     
	ULONG ulSize=sizeof(MIB_TCPTABLE2);
	PMIB_TCPTABLE2 pTcpTable = (PMIB_TCPTABLE2)malloc(ulSize);

	if (pTcpTable == nullptr)
		throw runtime_error("memory is not enough.");

	if (GetTcpTable2(pTcpTable, &ulSize, TRUE) == ERROR_INSUFFICIENT_BUFFER)
	{
     
		free(pTcpTable);
		pTcpTable = (PMIB_TCPTABLE2)malloc(ulSize);
		if (pTcpTable == nullptr)
			throw runtime_error("memory is not enough.");
	}

	if (GetTcpTable2(pTcpTable, &ulSize, TRUE) == NO_ERROR)
	{
     
		cout << "start finding TCP port:" << endl;
		for (int i = 0; i < pTcpTable->dwNumEntries; ++i)
		{
     
			unsigned short localPort = ntohs((u_short)pTcpTable->table[i].dwLocalPort);
			cout << localPort << endl;
			auto pid = pTcpTable->table[i].dwOwningPid;
			if (port == localPort)
			{
     
				cout << "found the destination port." << endl;
				return pid;
			}
		}
	}

	return 0;
}

int main(int argc, char* argv[])
{
     
	while (1)
	{
     
		unsigned short port;
		cout << "Please input a port number:";
		cin >> port;

		auto pid = GetIdOfOccupiedPortProcess(port);
		if (pid == 0)
		{
     
			cout << "No program." << endl;
			continue;
		}

		HANDLE hProcess = ::OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION, FALSE, pid);
		if (hProcess == NULL)
		{
     
			cout << "Failed in OpenProcess. Maybe no authorization." << endl;
			return -1;
		}

		TCHAR buf[MAX_PATH];
		if (GetModuleFileNameEx(hProcess, 0, buf, MAX_PATH))
		{
     
			cout << "Do you want to kill the process "<<buf <<"?(y/n)"<< endl;
		}
		else
		{
     
			cout << "Failed in GetModuleFileNameEx. Maybe no authorization." << endl;
			return -1;
		}

		char key;
		cin >> key;
		if (key == 'y')
		{
     
			if (::TerminateProcess(hProcess, 0))
				cout << "Success." << endl;
		}
		CloseHandle(hProcess);
	}

	return 0;
}

参考

GetTcpTable2 function
Build your own netstat.exe with c# | Tim Van Wassenhove’s blog
h
如何在C++中获取进程名?

你可能感兴趣的:(Win32,SDK,C-C++)