[CSAPP] 第三部分 第11章 网络 IP地址

IP地址

IP地址是32位无符号整数。网络程序讲IP地址存放在struct in_addr 中

struct in_addr{
    unsigned int s_addr;
}

IP地址总是以网络字节顺序(network byte order)(大端字节顺序)(big endian)存放,即使主机字节顺序是小端法(small endian)。
Unix 下有

#include <netinet/in.h>

unsigned long int htonl(unsigned long int hostlong);
unsigned short int htons(unsigned short int hostshort);
// host to network
unsigned long int ntohl(unsigned long int netlong);
unsigned short int ntohs(unsigned short int netshort);
// network to host

为了方便记忆,IP有点分十进制表示法,每个字节使用十进制表示并用句号分割开。转换函数如下:

#include <arpa/inet.h>

int inet_aton(const char *cp, struct in_addr *inp);
// application to network
char *inet_ntoa(struct in_addr in);
// network to application

练习

练习11.2

编写程序hex2dd.c,它将十六进制参数转换为点分十进制串并打印出结果。例如

unix> ./hex2dd 0x8002c2f2
128.2.194.242

解:

#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>
#include <netinet/in.h>

const char *useage = "useage: %s <hex IP like 0x7f000001>\n\ttranslate hex(network) to dd(application).\n";
int table[255];

void initTable()
{
    memset(table,-1,sizeof(table));
    table['0'] = 0;
    table['1'] = 1;
    table['2'] = 2;
    table['3'] = 3;
    table['4'] = 4;
    table['5'] = 5;
    table['6'] = 6;
    table['7'] = 7;
    table['8'] = 8;
    table['9'] = 9;
    table['a'] = table['A'] = 10;
    table['b'] = table['B'] = 11;
    table['c'] = table['C'] = 12;
    table['d'] = table['D'] = 13;
    table['e'] = table['E'] = 14;
    table['f'] = table['F'] = 15;
}


int readArg(int n,char *s[],struct in_addr *in)
{
    int i,j;
    in -> s_addr = 0;
    if(n != 2)
        return 0;
    else{
        n = strlen(s[1]);
        if( (n < 2 || n > 10)||(s[1][0] != '0' && 
                (s[1][1]!= 'x' || s[1][1] != 'X')))
            return 0;
        else
            for(i = ( n - 3 ) * 4,j = 2;j < n;i -= 4 , j++){
                if(table[s[1][j]] == -1)
                    return 0;
                in -> s_addr |= table[ s[1][j] ]<<i;
            }
    }
    in -> s_addr = ntohl(in -> s_addr);
    return 1;
}


int main(int argc,char *argv[])
{
    initTable();
    struct in_addr ip;
    if(readArg(argc,argv,&ip))
        printf("%s\n",inet_ntoa(ip));
    else
        fprintf(stderr,useage,argv[0]);
    return 0;
}

练习11.3

编写程序 dd2hex.c,它将它的点分十进制参数转换为十六进制数并打印出结果。例如

unix> ./dd2hex 128.2.194.242
0x8002c2f2

解:

#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>

const char *useage = "useage: %s 128.2.194.242\n\ttranslate dd(application) to hex(network).";

int main(int argc,char *argv[])
{
    if(argc != 2){
        fprintf(stderr,useage,argv[0]);
        return -1;
    }

    struct in_addr ip;
    if(!inet_aton(argv[1],&ip)){
        fprintf(stderr,useage,argv[0]);
        return -1;
    }

    printf("0x%x\n",htonl(ip.s_addr));
    return 0;
}

你可能感兴趣的:([CSAPP] 第三部分 第11章 网络 IP地址)