代码改变世界

网络编程--IP帮助函数

2011-06-21 20:15  Clingingboy  阅读(5016)  评论(3编辑  收藏  举报

 

一.GetNetworkParams获取本地电脑的网络参数

获取一个FIXED_INFO的结构体

typedef struct {
    char HostName[MAX_HOSTNAME_LEN + 4] ;
    char DomainName[MAX_DOMAIN_NAME_LEN + 4];
    PIP_ADDR_STRING CurrentDnsServer;
    IP_ADDR_STRING DnsServerList;
    UINT NodeType;
    char ScopeId[MAX_SCOPE_ID_LEN + 4];
    UINT EnableRouting;
    UINT EnableProxy;
    UINT EnableDns;
} FIXED_INFO_W2KSP1, *PFIXED_INFO_W2KSP1;
#if (NTDDI_VERSION >= NTDDI_WIN2KSP1)
typedef  FIXED_INFO_W2KSP1 FIXED_INFO;
typedef  FIXED_INFO_W2KSP1 *PFIXED_INFO;
#endif

二.网络接口管理

1.GetNumberOfInterfaces获取接口数量

DWORD GetNumberOfInterfaces(
  __out  PDWORD pdwNumIf
);

2.GetAdaptersInfo返回本地网络适配器列表

DWORD GetAdaptersInfo(
  __out    PIP_ADAPTER_INFO pAdapterInfo,
  __inout  PULONG pOutBufLen
);

int main()
{
    PIP_INTERFACE_INFO pInfo = 
            (PIP_INTERFACE_INFO)::GlobalAlloc(GPTR, sizeof(IP_INTERFACE_INFO));
    ULONG ulOutBufLen = sizeof(IP_INTERFACE_INFO);

    // 如果上面申请的内存不够的话,再重新申请
    if(::GetInterfaceInfo(pInfo, &ulOutBufLen) == ERROR_INSUFFICIENT_BUFFER)
    {
        ::GlobalFree(pInfo);
        pInfo = (PIP_INTERFACE_INFO)::GlobalAlloc(GPTR, ulOutBufLen);
    }

    // 再次调用GetInterfaceInfo来获取我们实际需要的数据
    if(::GetInterfaceInfo(pInfo, &ulOutBufLen) == NO_ERROR)
    {
        printf(" \tAdapter Name: %ws\n", pInfo->Adapter[0].Name);
        printf(" \tAdapter Index: %ld\n", pInfo->Adapter[0].Index);
        printf(" \tNum Adapters: %ld\n", pInfo->NumAdapters);
    }
    else
    {
        printf(" GetInterfaceInfo() failed \n");
    }

    ::GlobalFree(pInfo);
    return 0;
}

三.IP地址管理

获取IP地址列表、添加和删除IP地址
GetIpAddrTable、AddIPAddress、DeleteIPAddress

int main()
{
        // 首先调用GetIpAddrTable函数获取一个适配器
    PMIB_IPADDRTABLE pIPAddrTable;
    DWORD dwSize = 0;

    pIPAddrTable = (PMIB_IPADDRTABLE)::GlobalAlloc(GPTR, sizeof(MIB_IPADDRTABLE));

    // 获取所需的内存
    if(::GetIpAddrTable(pIPAddrTable, &dwSize, FALSE) == ERROR_INSUFFICIENT_BUFFER)
    {
        ::GlobalFree(pIPAddrTable);
        pIPAddrTable = (PMIB_IPADDRTABLE)::GlobalAlloc(GPTR, dwSize);
    }

    // 再次调用GetIpAddrTable获取实际我们想要的数据
    if(::GetIpAddrTable(pIPAddrTable, &dwSize, FALSE) == NO_ERROR)
    {
        // 打印出适配器信息
        printf(" Address: %ld\n", pIPAddrTable->table[0].dwAddr);
        printf(" Mask:    %ld\n", pIPAddrTable->table[0].dwMask);
        printf(" Index:   %ld\n", pIPAddrTable->table[0].dwIndex);
        printf(" BCast:   %ld\n", pIPAddrTable->table[0].dwBCastAddr);
        printf(" Reasm:   %ld\n", pIPAddrTable->table[0].dwReasmSize);
    }    
    else
    {
        printf(" GetIpAddrTable() failed \n");
    }
    
    ::GlobalFree(pIPAddrTable);
    
    // 我们将要添加的IP和mast
    UINT iaIPAddress;
    UINT imIPMask;
    
    iaIPAddress = inet_addr("192.168.0.27");
    imIPMask = inet_addr("255.255.255.0");
    
    // 返回的句柄
    ULONG NTEContext = 0;
    ULONG NTEInstance = 0;
    
    // 向第一个适配器添加IP地址
    DWORD dwRet;
    dwRet = ::AddIPAddress(iaIPAddress, imIPMask, 
                pIPAddrTable->table[0].dwIndex, &NTEContext, &NTEInstance);
    if(dwRet == NO_ERROR) 
    {
        printf(" IP address added.\n");
    }
    else 
    {
        printf(" AddIPAddress failed. \n");
        LPVOID lpMsgBuf;
        // 调用失败,打印出为什么失败
        if (::FormatMessage( 
            FORMAT_MESSAGE_ALLOCATE_BUFFER | 
            FORMAT_MESSAGE_FROM_SYSTEM | 
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            dwRet,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
            (LPTSTR) &lpMsgBuf,
            0,
            NULL )) 
        {
            printf(" Error: %s ", lpMsgBuf);
        }
        ::LocalFree(lpMsgBuf);
    }
    
    // 删除上面在第一个适配器上添加的IP地址
    dwRet = ::DeleteIPAddress(NTEContext);
    if(dwRet == NO_ERROR) 
    {
        printf(" IP Address Deleted.\n");
    }
    else 
    {        
        printf(" DeleteIPAddress failed.\n");
    }
    
    return 0;
}

四.获取网络状态信息

1.获取TCP和UDP连接表(GetTcpTable,GetUdpTable)

PMIB_UDPTABLE MyGetUdpTable(BOOL bOrder)
{
    PMIB_UDPTABLE pUdpTable = NULL;
    DWORD dwActualSize = 0;

    // 查询所需缓冲区的大小
    if(::GetUdpTable(pUdpTable, &dwActualSize, bOrder) == ERROR_INSUFFICIENT_BUFFER)
    {
        // 为MIB_UDPTABLE结构申请内存
        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);
}
// 打印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);
}


五.获取相关统计数据

相关的函数GetxxxStatistics(GetIpStatistics,GetIcmpStatistics,GetTcpStatistics,GetUdpStatistics)

// 获取UDP统计数据
MIB_UDPSTATS UdpStats;
if(::GetUdpStatistics(&UdpStats) == NO_ERROR)
{
    MIB_UDPSTATS *pStats = &UdpStats;
    printf("\nUDP Statistics\n");
    printf("\
              dwInDatagrams      = %lu\n\
              dwNoPorts          = %lu\n\
              dwInErrors         = %lu\n\
              dwOutDatagrams     = %lu\n\
              dwNumAddrs         = %lu\n",
              pStats->dwInDatagrams,
              pStats->dwNoPorts,
              pStats->dwInErrors,
              pStats->dwOutDatagrams,
              pStats->dwNumAddrs);
}

六.路由表管理

1.GetIpForwardTable获取路由表

PMIB_IPFORWARDTABLE MyGetIpForwardTable(BOOL bOrder)
{
    PMIB_IPFORWARDTABLE pIpRouteTab = NULL;
    DWORD dwActualSize = 0;
    
    // 查询所需缓冲区的大小
    if(::GetIpForwardTable(pIpRouteTab, &dwActualSize, bOrder) == ERROR_INSUFFICIENT_BUFFER)
    {
        // 为MIB_IPFORWARDTABLE结构申请内存
        pIpRouteTab = (PMIB_IPFORWARDTABLE)::GlobalAlloc(GPTR, dwActualSize);
        // 获取路由表
        if(::GetIpForwardTable(pIpRouteTab, &dwActualSize, bOrder) == NO_ERROR)
            return pIpRouteTab;
        ::GlobalFree(pIpRouteTab);
    }
    return NULL;
}
void PrintIpForwardTable()
{
    PMIB_IPFORWARDTABLE pIpRouteTable = MyGetIpForwardTable(TRUE);
    if(pIpRouteTable != NULL)
    {
        DWORD i, dwCurrIndex;
        struct in_addr inadDest;
        struct in_addr inadMask;
        struct in_addr inadGateway;  
        PMIB_IPADDRTABLE pIpAddrTable = NULL;
        
        char szDestIp[128];
        char szMaskIp[128];
        char szGatewayIp[128];

        printf("Active Routes:\n\n");
        
        printf("  Network Address          Netmask  Gateway Address        Interface  Metric\n");
        for (i = 0; i < pIpRouteTable->dwNumEntries; i++)
        {
            dwCurrIndex = pIpRouteTable->table[i].dwForwardIfIndex;
    
            // 目的地址
            inadDest.s_addr = pIpRouteTable->table[i].dwForwardDest;
            // 子网掩码
            inadMask.s_addr = pIpRouteTable->table[i].dwForwardMask;
            // 网关地址
            inadGateway.s_addr = pIpRouteTable->table[i].dwForwardNextHop;
            
            strcpy(szDestIp, inet_ntoa(inadDest));
            strcpy(szMaskIp, inet_ntoa(inadMask));
            strcpy(szGatewayIp, inet_ntoa(inadGateway));
            printf("  %15s %16s %16s %16d %7d\n", 
                szDestIp, 
                szMaskIp, 
                szGatewayIp, 
                pIpRouteTable->table[i].dwForwardIfIndex,    // 可以在此调用GetIpAddrTable获取索引对应的IP地址
                pIpRouteTable->table[i].dwForwardMetric1);
        }
        MyFreeIpForwardTable(pIpRouteTable);
    }
}

2.添加、删除、修改路由

CreateIpForwardEntry、DeleteIpForwardEntry、SetIpForwardEntry

七.ARP表管理

1.获取IP地址到适配器的映射关系,即ARP表(GetIpNetTable)

BOOL InterfaceIdxToInterfaceIp(PMIB_IPADDRTABLE pIpAddrTable, DWORD dwIndex, char str[])
{
    char* szIpAddr;

    if(pIpAddrTable == NULL ||  str == NULL)
        return FALSE;
    str[0] = '\0';
    // 遍历IP地址表,查找索引dwIndex对应的IP地址
    for(DWORD dwIdx = 0; dwIdx < pIpAddrTable->dwNumEntries; dwIdx++)
    {
        if(dwIndex == pIpAddrTable->table[dwIdx].dwIndex)
        {
            // 以字符串的形式返回查询结果
            szIpAddr = inet_ntoa(*((in_addr*)&pIpAddrTable->table[dwIdx].dwAddr));
            if(szIpAddr)
            {
                strcpy(str, szIpAddr);
                return TRUE;
            }
            else
                return FALSE;
        }
    }
    return FALSE;
}