Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3031882
  • 博文数量: 272
  • 博客积分: 5544
  • 博客等级: 大校
  • 技术积分: 5496
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-08 00:48
个人简介

  每个人都要有一个骨灰级的爱好,不为金钱,而纯粹是为了在这个领域享受追寻真理的快乐。

文章分类

全部博文(272)

文章存档

2015年(2)

2014年(5)

2013年(25)

2012年(58)

2011年(182)

分类: LINUX

2013-02-20 21:44:39

输入一个点分十进制的子网掩码地址, 转换为一个CIDR值, 比如输入255.255.255.0, 则得到24位掩码.

255.255.255.0的二进制表现为:

11111111 11111111 11111111 00000000


#include 
#include 
#include 

#if 0
static int ntod(u_int32_t mask) { //转换函数1
    int i, n = 0;
    int bits = sizeof(u_int32_t) * 8;
    for(i = bits - 1; i >= 0; i--) {
        if (mask & (0x01 << i)) 
            n++;
    }
    return n;
}
#else
static int ntod(u_int32_t mask) { //转换函数2
    float f;
    mask = -mask; //第一步
    f = mask; //第二步
    mask = *(unsigned *)&f; //第三步
    mask = 159 - (mask >> 23); //第四步
    return mask;
}
#endif

static u_int32_t dton(u_int32_t mask) { //转换函数3
    u_int32_t i, c;
    int bits = sizeof(u_int32_t) * 8;

    i = ~0;
    bits -= mask;
    /* 让32位全是1的无符号数与左移bits位(右移位用0填充)得出子网掩码 */
    i <<= bits;

    return htonl(i);
}

int main(void) {
	char  input[32];
	struct  in_addr addr;
	scanf("%s", input);
	if (inet_aton(input, &addr) == 0) {
		printf("netmask is wrong\n");
		exit(1);
	}
	addr.s_addr = htonl(addr.s_addr);
	printf("%d\n", ntod(addr.s_addr));
	return 0;
}
在转换函数1中, 使用的是最直接的方法, 通过对0x1左移位, 求出一共有多少个1, 从而得出子网掩码号.


本文的重点在于如果通过转换函数2得出子网掩码的, 这里我们先了解一下C语言对单精度浮点数的存储.


float一共32位, 其结构定义如下:
|-------- 31 -------|------------ 30-23 ------------ |------------ 22-0 ------------|
     符号位(sign)             指数部分(exp)                     底数(小数)部分(mag)


sign:符号位就一位, 0表示正数, 1表示负数
exp: 指数部分, 无符号正数
mag: 小数部分, 定点小数, 小数点在最左边


浮点数存储在第30位到第23位之间的8位上存储的是指数, 因为8位空间最多只能保存0~255个数, 所以能表示的有2的256次方, 但因为指数是可正可负的, 所以IEEE龟腚这里会有一个127的偏移量,它的127相当于0, 小于127时为负, 大于127时为正, 最高位为符号位. 这里我们是转换的正数, 所以exp=指数+127.
在这里我们先对函数接收的mask求负数(第一步), 也就是取反加1:


11111111 11111111 11111111 00000000
                ↓
00000000 00000001 00000000 00000000


得到256, 也就是2的8次方. 然后把这个整数转换为单精度浮点数储存(第二步), 因为该数为一个正整数, 所以sign=0, exp=127+8, 没有小数部分所以mag=0.
第三步把用单精度浮点数存储空间的内容又保存为无符号整形数(因为在32位机器上, 同为4个字节, 可以安全转换), 这样做的目的是因为单精度浮点数不能移位操作, 所以又转化为整形.
第四步先把mask右移23位, 因为最高位是0, 所以右移操作会补零, 得到我们的exp的值.这里我们做一个简单的方程, 设我们的子网掩码为x:
    exp-127=32-x
    exp-159=-x
    x=159-exp
就此我们的转换函数2完成.


最后一个转换函数3, 是传入一个小于等于32的数, 转换为32位的网络序的子网掩码.

阅读(12501) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

zooyo2013-02-21 22:55:16

那片依然海:zooyo,使用shell网络编程,能实现查看ntp服务器上的时间吗?就是执行exec 6<>/dev/udp/172.16.1.128/123,会打开一个到ntp服务器的通道,然后再去上面读取时间,可以吗?捣鼓一天了,也没实现了。。。不像python那么容易。

自己要改客户端吧

回复 | 举报

那片依然海2013-02-21 16:34:47

zooyo,使用shell网络编程,能实现查看ntp服务器上的时间吗?就是执行exec 6<>/dev/udp/172.16.1.128/123,会打开一个到ntp服务器的通道,然后再去上面读取时间,可以吗?捣鼓一天了,也没实现了。。。不像python那么容易。