#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <windows.h>
#include <iphlpapi.h>
#include <psapi.h>
#include <tlhelp32.h>
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
struct TcpConnection {
std::string localAddress;
std::string localPort;
std::string remoteAddress;
std::string remotePort;
std::string state;
DWORD pid;
std::string processName;
};
class NetStat {
private:
std::vector<TcpConnection> connections;
std::string getStateString(DWORD state) {
switch (state) {
case MIB_TCP_STATE_CLOSED: return "CLOSED";
case MIB_TCP_STATE_LISTEN: return "LISTENING";
case MIB_TCP_STATE_SYN_SENT: return "SYN_SENT";
case MIB_TCP_STATE_SYN_RCVD: return "SYN_RCVD";
case MIB_TCP_STATE_ESTAB: return "ESTABLISHED";
case MIB_TCP_STATE_FIN_WAIT1: return "FIN_WAIT1";
case MIB_TCP_STATE_FIN_WAIT2: return "FIN_WAIT2";
case MIB_TCP_STATE_CLOSE_WAIT: return "CLOSE_WAIT";
case MIB_TCP_STATE_CLOSING: return "CLOSING";
case MIB_TCP_STATE_LAST_ACK: return "LAST_ACK";
case MIB_TCP_STATE_TIME_WAIT: return "TIME_WAIT";
case MIB_TCP_STATE_DELETE_TCB: return "DELETE_TCB";
default: return "UNKNOWN";
}
}
std::string getProcessName(DWORD pid) {
if (pid == 0) return "System";
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
if (hProcess == NULL) return "Unknown";
char processName[MAX_PATH];
DWORD size = MAX_PATH;
if (QueryFullProcessImageNameA(hProcess, 0, processName, &size)) {
CloseHandle(hProcess);
std::string fullPath(processName);
size_t lastSlash = fullPath.find_last_of("\\/");
if (lastSlash != std::string::npos) {
return fullPath.substr(lastSlash + 1);
}
return fullPath;
}
CloseHandle(hProcess);
return "Unknown";
}
std::string formatAddress(DWORD address) {
struct in_addr addr;
addr.s_addr = address;
return std::string(inet_ntoa(addr));
}
std::string formatPort(DWORD port) {
return std::to_string(ntohs((u_short)port));
}
public:
bool getTcpConnections() {
DWORD size = 0;
DWORD result = GetExtendedTcpTable(NULL, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0);
if (result != ERROR_INSUFFICIENT_BUFFER) {
std::cerr << "GetExtendedTcpTable failed with error: " << result << std::endl;
return false;
}
std::vector<BYTE> buffer(size);
PMIB_TCPTABLE_OWNER_PID tcpTable = (PMIB_TCPTABLE_OWNER_PID)buffer.data();
result = GetExtendedTcpTable(tcpTable, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0);
if (result != NO_ERROR) {
std::cerr << "GetExtendedTcpTable failed with error: " << result << std::endl;
return false;
}
connections.clear();
for (DWORD i = 0; i < tcpTable->dwNumEntries; i++) {
MIB_TCPROW_OWNER_PID& row = tcpTable->table[i];
TcpConnection conn;
conn.localAddress = formatAddress(row.dwLocalAddr);
conn.localPort = formatPort(row.dwLocalPort);
conn.remoteAddress = formatAddress(row.dwRemoteAddr);
conn.remotePort = formatPort(row.dwRemotePort);
conn.state = getStateString(row.dwState);
conn.pid = row.dwOwningPid;
conn.processName = getProcessName(row.dwOwningPid);
connections.push_back(conn);
}
return true;
}
void printConnections() {
std::cout << std::left
<< std::setw(20) << "Local Address"
<< std::setw(10) << "Local Port"
<< std::setw(20) << "Remote Address"
<< std::setw(10) << "Remote Port"
<< std::setw(15) << "State"
<< std::setw(8) << "PID"
<< "Process Name" << std::endl;
std::cout << std::string(100, '-') << std::endl;
for (const auto& conn : connections) {
std::cout << std::left
<< std::setw(20) << conn.localAddress
<< std::setw(10) << conn.localPort
<< std::setw(20) << conn.remoteAddress
<< std::setw(10) << conn.remotePort
<< std::setw(15) << conn.state
<< std::setw(8) << conn.pid
<< conn.processName << std::endl;
}
std::cout << "\nTotal TCP connections: " << connections.size() << std::endl;
}
};
int main() {
std::cout << "TCP Connections (IPv4)" << std::endl;
std::cout << "======================" << std::endl << std::endl;
NetStat netstat;
if (!netstat.getTcpConnections()) {
std::cerr << "Failed to get TCP connections" << std::endl;
return 1;
}
netstat.printConnections();
return 0;
}