学习笔记《实战Linux Socket编程》第三章 地址转换函数

一、内容介绍
私有IP
分类    最低                   最高            网络掩码
A        10.0.0.0           10.255.255.255         255.0.0.0
B        172.16.0.0         172.31.255.255          255.255.0.0
C        192.168.0.0        192.168.255.255         255.255.255.0
 
保留IP(这是一个业余无线电预留IP)
A        44.0.0.0            44.255.255.255         255.0.0.0
 
二、代码实例:
1)
// IP地址分类
#include  < stdio.h >
#include 
< stdlib.h >
#include 
< unistd.h >
#include 
< sys / socket.h >
#include 
< sys / types.h >
#include 
< netinet / in .h >
#include 
< string .h >

int  main( int  argc,  char   * argv[])
{
    
int x;                          //索引变量
    struct sockaddr_in adr_inet;    //AF_INET
    int len_inet;                   //长度
    unsigned msb;                   //最有意义的字节
    char class;
    
char *netmask;
    
static struct
    
{
        unsigned 
char ip[4];
    }
addresses[] = {
        
{{44,135,86,12}},
        
{{127,0,0,1}},
        
{{172,16,23,95}},
        
{{192,168,9,1}}
    }
;

    
for (x = 0; x < 4++x)
    
{
    
//建立套接口地址,并说明分类方法
        memset(&adr_inet, 0sizeof(adr_inet));
        adr_inet.sin_family 
= AF_INET;
        adr_inet.sin_port 
= htons(9000);
        memcpy(
&adr_inet.sin_addr.s_addr, addresses[x].ip, 4);
        len_inet 
= sizeof(adr_inet);

        
//将adr_inet的第一个字节取出来,
        
//因为这个字节是IP地址中4个8位中的第一个8位组
        msb = *(unsigned char *)&adr_inet.sin_addr.s_addr;

        
/*地址分类
            1.获取是有意义的字节
            2.利用该字节进行分类
        
*/

        
if ((msb & 0x80== 0x00)//左端第一位为0
        {
            
class = 'A';
            netmask 
= "255.0.0.0";
        }
else if ((msb & 0xC0== 0x80)//左端第一位为1,第二位为0
        {
            
class = 'B';
            netmask 
= "255.255.0.0";
        }
else if ((msb & 0xE0== 0xC0)//左端前两位为11,第三位为0
        {
            
class = 'C';
            netmask 
= "255.255.255.0";
        }
else if ((msb & 0xF0== 0xE0)//左端4位为1110
        {
            
class = 'D';
            netmask 
= "255.255.255.255";
        }
else
        
{
            
class = 'E';
            netmask 
= "255.255.255.255";
        }


        printf(
"Address %u.%u.%u.%u is class %c"
                
"netmask %s ",
                addresses[x].ip[
0],
                addresses[x].ip[
1],
                addresses[x].ip[
2],
                addresses[x].ip[
3],
                
class, netmask);
    }

    
return 0;
}

2)
// 使用inet_addr进行IP地址操作
/*
将一个字符串常量转换成网络字节序的32位IP地址
这个函数已不太常用,使用inet_aton替代,
inet_addr()有错误时返回INADDR_NONE,但没有建立一个有效的errno值,所以不要去测试errno的值
*/

#include 
< stdio.h >
#include 
< stdlib.h >
#include 
< unistd.h >
#include 
< errno.h >
#include 
< string .h >
#include 
< sys / socket.h > //
#include  < sys / types.h >
#include 
< netinet / in .h > ///
#include  < arpa / inet.h > ///

// 报错函数
static   void  bail( char   * on_what)
{
    fputs(on_what, stderr);
    fputc(
' ', stderr);
    exit(
1);
}


int  main( int  argc,  char   * argv[])
{
    
int z;
    
struct sockaddr_in adr_inet;//AF_INET
    int len_inet;               //长度
    int sck_inet;               //套接口

    
//生成套接口
    sck_inet = socket(AF_INET, SOCK_STREAM, 0);

    
if (sck_inet == -1)
        bail(
"scoket()");

    
//建立套接口地址
    memset(&adr_inet, 0sizeof(adr_inet));

    adr_inet.sin_family 
= AF_INET;
    adr_inet.sin_port 
= htons(9000);
    adr_inet.sin_addr.s_addr 
= inet_addr("192.168.104.85");

    
if (adr_inet.sin_addr.s_addr == INADDR_NONE)
        bail(
"bad address");
    
    len_inet 
= sizeof(adr_inet);
    
    
//将地址绑定至套接口
    z = bind(sck_inet, (struct sockaddr *)&adr_inet, len_inet);

    
if (z == -1)
        bail(
"bind()");

    
//显示套接口地址
    system("netstat -pa --tcp | grep a.out");
    
//没有结果显示why?????

    
return 0;
}


3)
// gcc p58.c

// 使用inet_aton()进行IP操作
/*
#include <sys/socket.h>
#include <netinet/in.h>
#include <apra/inet.h>
int inet_aton(const char *string, struct in_addr *addr)
调用成功返回非0值,否则返回0值,它没有建立一个errno值,所以不要去测试errno
*/

#include 
< stdio.h >
#include 
< stdlib.h >
#include 
< unistd.h >
#include 
< errno.h >
#include 
< sys / socket.h >
#include 
< sys / types.h >
#include 
< netinet / in .h >
#include 
< arpa / inet.h > // 在ubuntu6.06中没有这个文件
#include  < string .h >

static   void  bail( const   char   * on_what)
{
    fputs(on_what, stderr);
    fputc(
' ', stderr);
    exit(
1);
}


int  main( int  argc,  char   * argv[])
{
    
int z;
    
struct sockaddr_in adr_inet;
    
int len_inet;
    
int sck_inet;

    sck_inet 
= socket(AF_INET, SOCK_STREAM, 0);

    
if (sck_inet == -1)
        bail(
"socket()");

    memset(
&adr_inet, 0sizeof(adr_inet));

    adr_inet.sin_family 
= AF_INET;
    adr_inet.sin_port 
= htons(9000);
    
if (! inet_aton("192.168.104.85"&adr_inet.sin_addr))
        bail(
"bad address");

    len_inet 
= sizeof(adr_inet);

    z 
= bind(sck_inet, (struct sockaddr *)&adr_inet, len_inet);

    
if (z == -1)
        bail(
"bind()");

    system(
"netstat -pa --tcp 2 > /dev/null | grep a.out");
    
//没有结果显示why?????
    return 0;
}


4)

/*
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
char *inet_ntoa(struct in_addr addr)
将套接口地址结构中网络字节序的32位二进制IP地址转换成一个字符串
*/

#include 
< stdio.h >
#include 
< stdlib.h >
#include 
< unistd.h >
#include 
< sys / socket.h >
#include 
< sys / types.h >
#include 
< arpa / inet.h >
#include 
< netinet / in .h >
#include 
< string .h >

int  main( int  argc,  char   * argv[])
{
    
struct sockaddr_in adr_inet;
    
int len_inet;

    memset(
&adr_inet, 0sizeof(adr_inet));

    adr_inet.sin_family 
= AF_INET;
    adr_inet.sin_port 
= htons(9000);
    
if (! inet_aton("192.168.1.2"&adr_inet.sin_addr))
        puts(
"bad address.");

    len_inet 
= sizeof(adr_inet);

    printf(
"The IP Address is %s ", inet_ntoa(adr_inet.sin_addr));

    
return 0;
}


5)
/*
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
unsigned long inet_network(const char *addr)
将点分十进制的addr转成主机字节序的32位二进制IP,出错的话返回0xFFFFFFFF
*/

#include 
< stdio.h >
#include 
< stdlib.h >
#include 
< sys / socket.h >
#include 
< sys / types.h >
#include 
< arpa / inet.h >
#include 
< netinet / in .h >
#include 
< unistd.h >
#include 
< string .h >

int  main( int  argc,  char   * argv[])
{
    
int x;
    
const char *addr[] = {
        
"44.135.86.12",
        
"127.0.0.1",
        
"172.16.23.95",
        
"192.168.9.1",
    }
;
    unsigned 
long net_addr;

    
for (x = 0; x < 4++x)
    
{
        net_addr 
= inet_network(addr[x]);
        printf(
"%14s = 0x%08lX net 0x%08lX ",
            addr[x], net_addr, (unsigned 
long)htonl(net_addr));
    }


    
return 0;
}


/*
运行结果:
44.135.86.12 =0x2C87560C net 0x0C56872C
127.0.0.1    =0x7F000001 net 0x0100007F
172.16.23.95 =0xAC10175F net 0x5F1710AC
192.168.9.1   =0xC0A80901 net 0x0109A8C0
第一列是原始的字符串IP
第二列是通过inet_network()转换出的主机字节序的32位二进制IP
第三列是网络字节序的32位二进制IP
因为是在Intel平台上,而intel是小端字节序,所以它的主机字节序与网络字节序不同,如果>在大端字节序的机器上后两列将是相同的
*/


6)

/*
函数inet_lnaof, inet_netof, inet_makeaddr使用示例

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

unsigned long inet_lnaof(struct in_addr addr)
输入是按网络字节序,输出是主机字节序
IP值                          IP分类     16进制                     点分10进制
44.135.86.12     A         0087560C       0.135.86.12
127.0.0.1        A         00000001       0.0.0.1
172.16.23.95     B         0000175F        0.0.23.95
192.168.9.1      C         00000001        0.0.0.1

unsigned long inet_netof(struct in_addr addr)
返回网络ID
IP值                          IP分类      16进制                     点分10进制
44.135.86.12     A         0000002C       0.0.0.44
127.0.0.1           A         0000007F       0.0.0.127
172.16.23.95     B         0000AC10        0.0.127.16
192.168.9.1      C         00C0A809        0.192.168.9
返回值是右对齐,主机位被移出

struct in_addr inet_makework(int net, int host)
net:代表网络位,这是右对齐的主机字节序,是inet_netof返回值
host:主机位,同样是主机字节序, 是inet_lnaof返回值
*/

#include 
< stdio.h >
#include 
< stdlib.h >
#include 
< unistd.h >
#include 
< sys / socket.h >
#include 
< sys / types.h >
#include 
< netinet / in .h >
#include 
< string .h >
#include 
< arpa / inet.h >

int  main( int  argc,  char   * argv[])
{
    
int x;
    
struct sockaddr_in adr_inet;
    
const char *addr[] = {
        
"44.135.86.12",
        
"127.0.0.1",
        
"172.16.23.95",
        
"192.168.9.1",
    }
;
    unsigned 
long net, hst;

    
for (x = 0; x < 4++x)
    
{
        memset(
&adr_inet, 0sizeof(adr_inet));
        adr_inet.sin_family 
= AF_INET;
        adr_inet.sin_port 
= htons(9000);
        
if (!inet_aton(addr[x], &adr_inet.sin_addr))
            puts(
"bad address.");

        hst 
= inet_lnaof(adr_inet.sin_addr);
        net 
= inet_netof(adr_inet.sin_addr);

        printf(
"%14s : net = 0x%08lX host = 0x%08lX ",
                inet_ntoa(adr_inet.sin_addr), net, hst);

        memset(
&adr_inet, 0sizeof(adr_inet));
        adr_inet.sin_family 
= AF_INET;
        adr_inet.sin_port 
= htons(9000);

        adr_inet.sin_addr 
= inet_makeaddr(net, hst);
                
        printf(
"%14s : %s ""inet_makeaddr", inet_ntoa(adr_inet.sin_addr));
    }


    
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值