有类别IP地址的程序分析

来源:互联网 发布:工业集成网络 编辑:程序博客网 时间:2024/06/06 20:23
/**********************************************************************/
/*              filename: ipParser.c        */
/*              author: huaiwen he          */
/*              date: 2008.5.13             */
/**********************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>

typedef unsigned long u_long;
typedef unsigned char u_char;

//存储IP 地址的数据结构
typedef union ip_addr{
    u_long addr;
    struct {u_char b1, b2, b3, b4;} addr_b;
} ip_addr;
//判断IP地址的类别
#define IS_CLASSA(i)    (((long)(i) & 0x80000000) == 0)
#define IS_CLASSB(i)    (((long)(i) & 0xc0000000) == 0x80000000)
#define IS_CLASSC(i)    (((long)(i) & 0xe0000000) == 0xc0000000)
#define IS_CLASSD(i)    (((long)(i) & 0xf0000000) == 0xe0000000)

//有类别IP地址的子网掩码
const char* SUBNET_MASK[] ={ "255.0.0.0",
                              "255.255.0.0"
                             "255.255.255.0"};
/*函数声明*/
void ipToString(const u_long ipAddr, char str[]);
int stringToIp(const char ipStr[], u_long* ipAddr);
void printBinary(const u_long ipAddr);
int getIpClass(u_long ipAddr);
u_long getNetIdOfClassIp(const u_long ipAddr);
u_long getBAddrOfClassIp(const u_long ipAddr);
u_long getHostIdOfClassIp(const u_long ipAddr);
/**************************************************************************/
/*函数原型: u_long getNetId(u_long ipAddr)              */
/*参数: u_long ipAddr  有类别的IP地址                   */
/*返回值: u_long Ip地址所在的网络号网络号,如果返回值为0,表示
           该IP地址不存在网络号                             */
/**************************************************************************/
u_long getNetIdOfClassIp(const u_long ipAddr)
{
    u_long ip_addr = ipAddr;
    int ipClass;
    ipClass = getIpClass(ip_addr);
    switch(ipClass)
    {
    /*A类IP地址*/
    case 0:
        return (0xff000000 & ip_addr);
    /*B类IP地址*/
    case 1:
        return (0xffff0000 & ip_addr);
    /*C类IP地址*/
    case 2:
        return (0xffffff00 & ip_addr);
    default:
        printf("该IP地址不存在网络号/n");
        return (u_long)0;
    }
}

u_long getBAddrOfClassIp(const u_long ipAddr)
{
    u_long ip_addr = ipAddr;
    int ipClass;
    ipClass = getIpClass(ip_addr);
    switch(ipClass)
    {
    case 0:
        return (0x00ffffff | ip_addr);
    case 1:
        return (0x0000ffff | ip_addr);
    case 2:
        return (0x000000ff | ip_addr);
    default:
        printf("该网络不存在广播地址/n");
        return (u_long)0;
    }
}
u_long getHostIdOfClassIp(const u_long ipAddr)
{
    u_long ip_addr = ipAddr;
    int ipClass = getIpClass(ip_addr);
    switch(ipClass)
    {
    case 0:
        return (0x00ffffff & ip_addr);
    case 1:
        return (0x0000ffff & ip_addr);
    case 2:
        return (0x000000ff & ip_addr);
    default:
        printf("该IP地址不存在主机号/n");
        return (u_long)0;
    }
}
/**********************************************************************/
/* 函数原型:ipToString(const u_long ipAddr, char str[]) */
/* 参数: u_long ipAddr(长整类型的IP地址),
          char* str(数组,大小为16byte)                  */
/* 返回值:int,成功返回1,失败返回-1                     */
/* 函数功能:将长整类型的IP地址转换为点分十进制的字符串表示形式*/
/**********************************************************************/
void ipToString(const u_long ipAddr, char str[])
{
    ip_addr ip;
    ip.addr = ipAddr;
    sprintf(str, "%d.%d.%d.%d", ip.addr_b.b4, ip.addr_b.b3,
                                ip.addr_b.b2, ip.addr_b.b1);
}

/**********************************************************************/
/* 函数原型:printBinary(const u_long ipAddr)            */
/* 参数: u_long ipAddr(长整类型的IP地址)                */
/* 返回值:void                                          */
/* 函数功能:打印输出一个长整形的IP地址的二进制形式      */
/**********************************************************************/
void printBinary(const u_long ipAddr)
{
    int i;
    u_long ip = ipAddr;
    /*逐位输出最高位*/
    for(i = 1; i <= 32; ++i)
    {
        (ip&0x80000000) ? printf("1") : printf("0");
         ip <<= 1;
        (i%8) ? printf("") : printf("  ");    /*逢一个字节就输出空格*/
    }
    printf("/n");
}
/**********************************************************************/
/* 函数原型:stringToIp(const char* ipStr, u_long* ipAddr)        */
/* 参数: char* ipStr(点分十进制表示的IP地址)
          u_long* ipAddr(长整型的IP地址)                        */
/* 返回值:int                                                    */
/* 函数功能:将字符串形式的IP地址转换为长整型的IP地址,如果字符串错误
             ,返回-1,否则返回1. 并将IP地址存储在ipAddr中          */
/**********************************************************************/
int stringToIp(const char ipStr[], u_long* ipAddr)
{
    ip_addr ip;
    int byte[4];            //保存每个字节的数值
    int i = 0;              // 用于遍历字符串
    int byteVal = 0;       // 每个字节十进制数值
    int dotCount = 0;      // '.'符号的个数
    if(ipStr == NULL)
    {
        printf("Bad Argument: ipAddr is invalid./n");
        return -1;
    }
    while(ipStr[i])
    {
        //如果字符不为数字或者不是'.',返回-1.
        if((ipStr[i] < '0'||ipStr[i] > '9')
            && (ipStr[i] != '.'))
            return -1;
        //字符串长度大于16,返回-1
        if(i >= 16)
            return (-1);
        //遇到'.'字符
        else if(ipStr[i] == '.')
        {
            //'.'次数大于3或者后一位也是'.',返回-1
            if(dotCount > 3 || ipStr[i+1] == '.')
                return (-1);
            // 判断'.'是否出现在首位或末位
            if(i == 0 || ipStr[i+1]=='/0')
                return (-1);
            byte[dotCount] = byteVal; // 获取前一个字节的值
            dotCount++;
            byteVal = 0;  //重置字节的值为0
        }
        else
        {
            // 字节数值以0开头
            if(byteVal == 0 && ipStr[i] == '0')
                return (-1);
            //计算该字节的数值
            byteVal = (byteVal*10) + (ipStr[i] - '0');          
            if(byteVal < 0 || byteVal > 255)
                return -1;
        }
        i++;
    }
    //如何'.'小于3个,返回-1
    if(dotCount < 3)
        return -1;
    //dotCount等于3,得到最后一个字节的整数
    byte[dotCount] = byteVal;
    //将得到的整数组成长整型的IP地址
    ip.addr_b.b1 = byte[3];
    ip.addr_b.b2 = byte[2];
    ip.addr_b.b3 = byte[1];
    ip.addr_b.b4 = byte[0];
    *ipAddr = ip.addr;
    return 1;
}
/*
  判断IP地址的类别
*/
int getIpClass(const u_long ipAddr)
{
    if(IS_CLASSA(ipAddr))
        return 0;
    if(IS_CLASSB(ipAddr))
        return 1;
    if(IS_CLASSC(ipAddr))
        return 2;
    if(IS_CLASSD(ipAddr))
        return 3;
    else
        return 4;
}
void usage()
{
    printf("/n/n用法:IP地址大小为4个字节,共32位。由<网络号,主机号>两部分"
        "组成。/n在计算机内往往使用一个4字节的长整型变量来存储。/n有类别"
        "的IP地址分为A、B、C、D、E五类。其中常用的有A、B、C三类。/n"
        "/n本程序用于分析一个有类别的IP地址.包括判断输入IP地址的合法性、/n"
        "并输出IP地址的二进制表示形式,判断IP地址的类别,/n输出IP地址所在"
        "的网络号、主机号以及广播地址/n"
        "作者: huaiwen he/n"
        "时间: 2008年5月16日/n");
}

/***************************************************************************/
/* 函数原型:pause()                                    */
/* 返回值:void                                            */
/* 函数功能:暂停目前的程序,用户按回车键继续            */
/***************************************************************************/
void pause()
{
    fflush(stdin);    /*清空输入流*/
    printf("/nPlease Press Enter to continue.../n");
    int ch;
    while(1)
        if((ch=getchar()) == '/n')   /*如果不是按回车键*/
            break;

}

/* 主函数 */
int main()
{
    char inputStr[80];     // 输入字符串
    char ipAddrStr[4*4];   // 保存IP地址字符串形式
    u_long ipAddr;         //保存长整数类型的IP地址
    int ipClass;           // 保存IP地址的类别

    usage();
    pause();
    while(1)
    {
        system("cls");
        printf("/n请输入一个IP地址或者输入q(Q)退出程序:/n");
        scanf("%s", inputStr);
        printf("/n-------------------------------------------------------/n");
        /*如果输入q或者Q,推出程序*/
        if((inputStr[0]=='q')||(inputStr[0] == 'Q'))
        {
            pause();
            exit(0); /*退出程序*/       
        }
        /*判断IP地址的合法性*/
        if(stringToIp(inputStr, &ipAddr) < 0)  /*非法IP地址*/
        {
            printf("=====Error: Bad IP Address %s./n", inputStr);
        }
        else
        {
            printf("/n输入的IP地址 %s 在系统中以unsigned long int类型存储",
                    inputStr);
            printf("/n该IP 地址对应的二进制为:/n/t");
            printBinary(ipAddr);
            /*获得IP地址的类别*/
            ipClass = getIpClass(ipAddr);
            printf("/t该IP地址属于%c类IP/n",  ('A'+ipClass));
            /*获得IP地址所属的网络*/
            ipToString(getNetIdOfClassIp(ipAddr), ipAddrStr);
            printf("/t该IP地址的网络号为%s/n", ipAddrStr);
            /*获得IP地址的主机号*/
            ipToString(getHostIdOfClassIp(ipAddr), ipAddrStr);
            printf("/t该IP地址的主机号为%s/n", ipAddrStr);
            /*获得该网络的广播地址*/
            ipToString(getBAddrOfClassIp(ipAddr), ipAddrStr);
            printf("/t该网络的广播地址为%s/n", ipAddrStr);
        }
        pause();
    }
}
原创粉丝点击