반응형
#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;
}

'Develop > C&CPP' 카테고리의 다른 글

[cpp] optional  (0) 2025.04.25
[cpp] thread  (0) 2025.04.20
[cpp] atomic  (0) 2025.04.20
[cpp] mutex, lock  (0) 2025.04.20
[cpp] cpp17에서 달라진 점  (0) 2025.04.20

+ Recent posts