c++ 使用进程id获取打开的网络端口

#pragma warning( disable : 4996)

#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <string>
#include <vector>

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

#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))

using namespace std;

string toIp(DWORD ip)
{
  size_t a = ip >> 24 & 0xFF;
  size_t b = ip >> 16 & 0xFF;
  size_t c = ip >> 8 & 0xFF;
  size_t d = ip & 0xFF;

  // 数据是大端就用 abcd,小端dcba
  return string(to_string(d) + "." + to_string(c) + "." + to_string(b) + "." + to_string(a));
}

struct ConnectNet
{
  DWORD proto = 0; // 6 tcp,17 udp
  string src; // src ip
  u_short sport; // src port
  string dst; // dst ip
  u_short dport; // dst port
  string state;
  DWORD pid; // process id
};

BOOL eachTCP(DWORD pid, vector<ConnectNet>* connectNets)
{
  PMIB_TCPTABLE2 pTcpTable = nullptr;
  ULONG ulSize = 0;
  DWORD dwRetVal = 0;

  // 第一次获取大小,初始化pTcpTable
  if ((dwRetVal = GetTcpTable2(pTcpTable, &ulSize, TRUE)) ==
    ERROR_INSUFFICIENT_BUFFER) {
    pTcpTable = (MIB_TCPTABLE2*)MALLOC(ulSize);
    if (pTcpTable == NULL) return 0;
  }

  // 第二次获取数据
  if ((dwRetVal = GetTcpTable2(pTcpTable, &ulSize, TRUE)) == NO_ERROR) {
    if (pTcpTable == NULL) return 0;

    for (size_t i = 0; i < pTcpTable->dwNumEntries; i++) {
      auto it = pTcpTable->table[i];
      if (pid != it.dwOwningPid && pid != 0) continue;
      string state = "";
      switch (it.dwState) {
      case MIB_TCP_STATE_CLOSED:
        state = "CLOSED";
        break;
      case MIB_TCP_STATE_LISTEN:
        state = "LISTEN";
        break;
      case MIB_TCP_STATE_SYN_SENT:
        state = ("SYN-SENT");
        break;
      case MIB_TCP_STATE_SYN_RCVD:
        state = ("SYN-RECEIVED");
        break;
      case MIB_TCP_STATE_ESTAB:
        state = ("ESTABLISHED");
        break;
      case MIB_TCP_STATE_FIN_WAIT1:
        state = ("FIN-WAIT-1");
        break;
      case MIB_TCP_STATE_FIN_WAIT2:
        state = ("FIN-WAIT-2");
        break;
      case MIB_TCP_STATE_CLOSE_WAIT:
        state = ("CLOSE-WAIT");
        break;
      case MIB_TCP_STATE_CLOSING:
        state = ("CLOSING");
        break;
      case MIB_TCP_STATE_LAST_ACK:
        state = ("LAST-ACK");
        break;
      case MIB_TCP_STATE_TIME_WAIT:
        state = ("TIME-WAIT");
        break;
      case MIB_TCP_STATE_DELETE_TCB:
        state = ("DELETE-TCB");
        break;
      default:
        state = ("UNKNOWN dwState value");
        break;
      }

      connectNets->push_back(ConnectNet{
        6,
        toIp(it.dwLocalAddr), ntohs((u_short)it.dwLocalPort),
        toIp(it.dwRemoteAddr), ntohs((u_short)it.dwRemotePort),
        state,
        it.dwOwningPid
        });
    }
  }
  else {
    FREE(pTcpTable);
    return FALSE;
  }

  if (pTcpTable != NULL) {
    FREE(pTcpTable);
    pTcpTable = NULL;
  }
  return TRUE;
}

BOOL eachUDP(DWORD pid, vector<ConnectNet>* connectNets)
{
  MIB_UDPTABLE_OWNER_PID* pUdpTable = nullptr;
  ULONG ulSize = 0;
  DWORD dwRetVal = 0;

  // 第一次获取大小,初始化pTcpTable
  if ((dwRetVal = GetExtendedUdpTable(pUdpTable, &ulSize, TRUE, AF_INET, UDP_TABLE_CLASS::UDP_TABLE_OWNER_PID, 0)) ==
    ERROR_INSUFFICIENT_BUFFER) {
    pUdpTable = (MIB_UDPTABLE_OWNER_PID*)MALLOC(ulSize);
    if (pUdpTable == NULL) return 0;
  }

  // 第二次获取数据
  if ((dwRetVal = GetExtendedUdpTable(pUdpTable, &ulSize, TRUE, AF_INET, UDP_TABLE_CLASS::UDP_TABLE_OWNER_PID, 0)) == NO_ERROR) {
    if (pUdpTable == NULL) return 0;
    
    for (size_t i = 0; i < pUdpTable->dwNumEntries; i++) {
      auto it = pUdpTable->table[i];
      if (it.dwOwningPid != pid && pid != 0) continue;
      connectNets->push_back(ConnectNet{
        17,
        toIp(it.dwLocalAddr).c_str(), ntohs((u_short)it.dwLocalPort),
        "*", 0,
        "",
        it.dwOwningPid
        });

    }
  }
  else {
    FREE(pUdpTable);
    return FALSE;
  }

  if (pUdpTable != NULL) {
    FREE(pUdpTable);
    pUdpTable = NULL;
  }
  return TRUE;
}

BOOL getNetTable(DWORD pid, vector<ConnectNet>* connectNets)
{
  if (!eachTCP(pid, connectNets)) return FALSE;
  return eachUDP(pid, connectNets);
}

// https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-gettcptable2
// https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getudptable
int main()
{
  vector<ConnectNet> r;
  if (getNetTable(0, &r))
  {
    for (auto it : r)
    {
      if (it.proto == 6)
      {
        printf("	%s	%s:%d	%s:%d	%s	%d
", "TCP", it.src.c_str(), it.sport, it.dst.c_str(), it.dport, it.state.c_str(), it.pid);
      }
      else if (it.proto == 17)
      {
        printf("	%s	%s:%d	%s:%s		%d
", "UDP", it.src.c_str(), it.sport, it.dst.c_str(), it.dport, it.pid);
      }
    }
  }
  return 0;
}
原文地址:https://www.cnblogs.com/ajanuw/p/13693161.html