欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-01 12:12:16
...

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

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

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

源码:

#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include <iostream>
#include <ws2tcpip.h>

#include <Windows.h>
#include <psapi.h>//GetModuleFileNameEx

#include <iphlpapi.h>
#pragma comment(lib, "iphlpapi.lib")

#include <winsock2.h>
#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++