VC++实现获取所有的TCP与UDP链接

来源:岁月联盟 编辑:exp 时间:2012-09-04
我们亲自来实现获取所有的TCP与UDP的网络链接。
 
[cpp]
  
[cpp] 
<p>/*</p><p>定义协议格式
定义协议中使用的宏</p><p> */</p><p> 
#ifndef __PROTOINFO_H__ 
#define __PROTOINFO_H__</p><p> 
#define ETHERTYPE_IP    0x0800 
#define ETHERTYPE_ARP   0x0806</p><p>typedef struct _ETHeader         // 14字节的以太头 

 UCHAR dhost[6];   // 目的MAC地址destination mac address 
 UCHAR shost[6];   // 源MAC地址source mac address 
 USHORT type;    // 下层协议类型,如IP(ETHERTYPE_IP)、ARP(ETHERTYPE_ARP)等 
} ETHeader, *PETHeader;</p><p> 
#define ARPHRD_ETHER  1</p><p>// ARP协议opcodes 
#define ARPOP_REQUEST 1  // ARP 请求  
#define ARPOP_REPLY  2  // ARP 响应</p><p> 
typedef struct _ARPHeader  // 28字节的ARP头 

 USHORT hrd;    // 硬件地址空间,以太网中为ARPHRD_ETHER 
 USHORT eth_type;   //  以太网类型,ETHERTYPE_IP ?? 
 UCHAR maclen;    // MAC地址的长度,为6 
 UCHAR iplen;    // IP地址的长度,为4 
 USHORT opcode;    // 操作代码,ARPOP_REQUEST为请求,ARPOP_REPLY为响应 
 UCHAR smac[6];   // 源MAC地址 
 UCHAR saddr[4];   // 源IP地址 
 UCHAR dmac[6];   // 目的MAC地址 
 UCHAR daddr[4];   // 目的IP地址 
} ARPHeader, *PARPHeader;</p><p> 
// 协议 
#define PROTO_ICMP    1 
#define PROTO_IGMP    2 
#define PROTO_TCP     6 
#define PROTO_UDP     17</p><p>typedef struct _IPHeader  // 20字节的IP头 

    UCHAR     iphVerLen;      // 版本号和头长度(各占4位) 
    UCHAR     ipTOS;          // 服务类型  
    USHORT    ipLength;       // 封包总长度,即整个IP报的长度 
    USHORT    ipID;     // 封包标识,惟一标识发送的每一个数据报 
    USHORT    ipFlags;       // 标志 
    UCHAR     ipTTL;       // 生存时间,就是TTL 
    UCHAR     ipProtocol;     // 协议,可能是TCP、UDP、ICMP等 
    USHORT    ipChecksum;     // 校验和 
    ULONG     ipSource;       // 源IP地址 
    ULONG     ipDestination;  // 目标IP地址 
} IPHeader, *PIPHeader; </p><p> 
// 定义TCP标志 
#define   TCP_FIN   0x01 
#define   TCP_SYN   0x02 
#define   TCP_RST   0x04 
#define   TCP_PSH   0x08 
#define   TCP_ACK   0x10 
#define   TCP_URG   0x20 
#define   TCP_ACE   0x40 
#define   TCP_CWR   0x80</p><p>typedef struct _TCPHeader  // 20字节的TCP头 

 USHORT sourcePort;   // 16位源端口号 
 USHORT destinationPort; // 16位目的端口号 
 ULONG sequenceNumber;  // 32位序列号 
 ULONG acknowledgeNumber; // 32位确认号 
 UCHAR dataoffset;   // 高4位表示数据偏移 
 UCHAR flags;    // 6位标志位 
        //FIN - 0x01 
        //SYN - 0x02 
        //RST - 0x04  
        //PUSH- 0x08 
        //ACK- 0x10 
        //URG- 0x20 
        //ACE- 0x40 
        //CWR- 0x80</p><p> USHORT windows;   // 16位窗口大小 
 USHORT checksum;   // 16位校验和 
 USHORT urgentPointer;  // 16位紧急数据偏移量  
} TCPHeader, *PTCPHeader;</p><p>typedef struct _UDPHeader 

 USHORT   sourcePort;  // 源端口号   
 USHORT   destinationPort;// 目的端口号   
 USHORT   len;   // 封包长度 
 USHORT   checksum;  // 校验和 
} UDPHeader, *PUDPHeader;</p><p>#endif // __PROTOINFO_H__ 
</p>#include <stdio.h> 
#include <windows.h> 
#include <Iphlpapi.h> 
 
#pragma comment(lib, "Iphlpapi.lib") 
#pragma comment(lib, "WS2_32.lib") 
 
 
PMIB_TCPTABLE MyGetTcpTable(BOOL bOrder); 
PMIB_UDPTABLE MyGetUdpTable(BOOL bOrder); 
 
void MyFreeTcpTable(PMIB_TCPTABLE pTcpTable); 
void MyFreeUdpTable(PMIB_UDPTABLE pUdpTable); 
 
 
int main() 

    // 打印TCP连接表信息 
    PMIB_TCPTABLE pTcpTable = MyGetTcpTable(TRUE); 
    if(pTcpTable != NULL) 
    { 
        char    strState[128]; 
        struct  in_addr    inadLocal, inadRemote; 
        DWORD   dwRemotePort = 0; 
        char    szLocalIp[128]; 
        char    szRemIp[128]; 
 
        printf("TCP TABLE/n"); 
        printf("%20s %10s %20s %10s %s/n", "Loc Addr", "Loc Port", "Rem Addr", 
            "Rem Port", "State"); 
        for(UINT i = 0; i < pTcpTable->dwNumEntries; ++i) 
        { 
            // 状态 
            switch (pTcpTable->table[i].dwState) 
            { 
            case MIB_TCP_STATE_CLOSED: 
                strcpy(strState, "CLOSED"); 
                break; 
            case MIB_TCP_STATE_TIME_WAIT: 
                strcpy(strState, "TIME_WAIT"); 
                break; 
            case MIB_TCP_STATE_LAST_ACK: 
                strcpy(strState, "LAST_ACK"); 
                break; 
            case MIB_TCP_STATE_CLOSING: 
                strcpy(strState, "CLOSING"); 
                break; 
            case MIB_TCP_STATE_CLOSE_WAIT: 
                strcpy(strState, "CLOSE_WAIT"); 
                break; 
            case MIB_TCP_STATE_FIN_WAIT1: 
                strcpy(strState, "FIN_WAIT1"); 
                break; 
            case MIB_TCP_STATE_ESTAB: 
                strcpy(strState, "ESTAB"); 
                break; 
            case MIB_TCP_STATE_SYN_RCVD: 
                strcpy(strState, "SYN_RCVD"); 
                break; 
            case MIB_TCP_STATE_SYN_SENT: 
                strcpy(strState, "SYN_SENT"); 
                break; 
            case MIB_TCP_STATE_LISTEN: 
                strcpy(strState, "LISTEN"); 
                break; 
            case MIB_TCP_STATE_DELETE_TCB: 
                strcpy(strState, "DELETE"); 
                break; 
            default: 
                printf("Error: unknown state!/n"); 
                break; 
            } 
            // 本地地址 
            inadLocal.s_addr = pTcpTable->table[i].dwLocalAddr; 
             
            // 远程端口 
            if (strcmp(strState, "LISTEN") != 0) 
            { 
                dwRemotePort = pTcpTable->table[i].dwRemotePort; 
            } 
            else 
                dwRemotePort = 0; 
            // 远程IP地址 
            inadRemote.s_addr = pTcpTable->table[i].dwRemoteAddr; 
 
            strcpy(szLocalIp, inet_ntoa(inadLocal)); 
            strcpy(szRemIp, inet_ntoa(inadRemote)); 
            printf("%20s %10u %20s %10u %s/n",  
                szLocalIp,  ntohs((unsigned short)(0x0000FFFF & pTcpTable->table[i].dwLocalPort)), 
                szRemIp, ntohs((unsigned short)(0x0000FFFF & dwRemotePort)), 
                strState); 
        } 
        MyFreeTcpTable(pTcpTable); 
    } 
 
    printf(" /n/n"); 
 
    // 打印UDP监听表信息 
    PMIB_UDPTABLE pUdpTable = MyGetUdpTable(TRUE); 
    if(pUdpTable != NULL) 
    { 
        struct in_addr inadLocal; 
        printf("UDP TABLE/n"); 
 
        printf("%20s %10s/n", "Loc Addr", "Loc Port"); 
        for (UINT i = 0; i < pUdpTable->dwNumEntries; ++i) 
        { 
            inadLocal.s_addr = pUdpTable->table[i].dwLocalAddr; 
            // 打印出此入口的信息 
            printf("%20s %10u /n",  
                inet_ntoa(inadLocal), ntohs((unsigned short)(0x0000FFFF & pUdpTable->table[i].dwLocalPort))); 
        } 
 
        MyFreeUdpTable(pUdpTable); 
    } 
         
    return 0; 

 
 
PMIB_TCPTABLE MyGetTcpTable(BOOL bOrder) 

    PMIB_TCPTABLE pTcpTable = NULL; 
    DWORD dwActualSize = 0; 
 
 
    // 查询所需缓冲区的大小 
    if(::GetTcpTable(pTcpTable, &dwActualSize, bOrder) == ERROR_INSUFFICIENT_BUFFER) 
    { 
        // 为MIB_TCPTABLE结构申请内存 
        pTcpTable = (PMIB_TCPTABLE)::GlobalAlloc(GPTR, dwActualSize); 
        // 获取TCP连接表 
        if(::GetTcpTable(pTcpTable, &dwActualSize, bOrder) == NO_ERROR) 
            return pTcpTable; 
        ::GlobalFree(pTcpTable); 
    } 
    return NULL; 

 
void MyFreeTcpTable(PMIB_TCPTABLE pTcpTable) 

    if(pTcpTable != NULL) 
        ::GlobalFree(pTcpTable); 

 
 
PMIB_UDPTABLE MyGetUdpTable(BOOL bOrder) 

    PMIB_UDPTABLE pUdpTable = NULL; 
    DWORD dwActualSize = 0; 
 
    // 查询所需缓冲区的大小 
    if(::GetUdpTable(pUdpTable, &dwActualSize, bOrder) == ERROR_INSUFFICIENT_BUFFER) 
    { 
        // 为MIB_UDPTABLE结构申请内存  www.2cto.com
        pUdpTable = (PMIB_UDPTABLE)::GlobalAlloc(GPTR, dwActualSize); 
        // 获取UDP监听表 
        if(::GetUdpTable(pUdpTable, &dwActualSize, bOrder) == NO_ERROR) 
            return pUdpTable; 
        ::GlobalFree(pUdpTable); 
    } 
    return NULL; 

 
void MyFreeUdpTable(PMIB_UDPTABLE pUdpTable) 

    if(pUdpTable != NULL) 
        ::GlobalFree(pUdpTable);