WinSock网络编程学习笔记(四)网络转换函数的实现

来源:互联网 发布:网络接口转换器 编辑:程序博客网 时间:2024/04/29 19:20

WinSock提供了IP地址和点分十进制地址之间的转换函数,IP地址在网络模块中使用,点分十进制则是方便平常我们阅读而存在。

今天初步认识了下两个转换函数:

1.

函数原型:

unsigned long WSAAPI inet_addr(const char FAR*cp);

返回值:

成功返回一个32位二进制描述的网络字节序地址;如果传入的字符串不是合法地址,函数失败且返回INADDR_NONE,WinSock中定义为0xffffffff;

如“a,b,c,d”之中的任意一部分超过255都将导致错误。而当输入的地址是广播地址"255.255.255.255"时,

函数也返回错误值。因此该函数不能用于对广播地址进行转换。

2.

函数原型:

unsigned long WSAAPI inet_ntoa(struct in_addr in);

返回值:

成功返回一个指向静态缓冲区的指针。失败返回NULL。该函数用于把网络字节序的IP地址转换为点分十进制的IP地址。

下面是原书中的代码,我只是加了一些注释,方便像和我一样的同学学习,呵呵。

NetConvt.c

#include<stdio.h>#include<winsock2.h>//需要使用其中的 struct in_addr 数据结构#define INADDR_INVALD 0xffffffff//无效地址static unsigned long range[] = {0xffffffff,0xffffff,0xffff,0xff};//函数 net_htons 和 net_ntohs 是 短整数 主机字节序和网络字节序之间的转换,都是左移,//只有在小尾数的机器上需要这样的实现,如果是大尾数的机器,直接返回传入的参数即可。unsigned short net_htons(unsigned short shost){unsigned char *p = (unsigned char *)&shost;return (unsigned short)(p[0] << 8 | p[1]);//短整型占两个字节,把高字节和低字节交换位置}unsigned short net_ntohs(unsigned short snet){unsigned char *p = (unsigned char *)&snet;return (unsigned short)(p[0] << 8 | p[1]);}//函数 net_htonl 和 net_ntohl 是 长整数 主机字节序和网络字节序之间的转换unsigned long net_htonl(unsigned long lhost){unsigned char *p = (unsigned char *)&lhost;return(unsigned long)(p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24));//长整数占4个字节} unsigned long net_ntohl(unsigned long lnet){unsigned char *p = (unsigned char *)&lnet;return(unsigned long)(p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24));} //net_ntoa该函数将网络字节序的IP地址转换为点分十进制的IP地址。char *net_ntoa(struct in_addr addr){static char buf[16];//转换后最大长度为15unsigned char *p = (unsigned char*)&addr;sprintf(buf,"%d.%d.%d.%d",p[0],p[1],p[2],p[3]);return buf;}//下面这个函数是将点分十进制的IP地址转换为网络字节序的IP地址unsigned long net_addr(const char *cp){unsigned char addr[4],*p = addr,c = *cp;//c 为指针cp当前指向的地址中的值..unsigned long value;int i,n,base,digit;while(1)//循环解析{base = 10,value = 0,digit = 0;//判断头号位是10进制还是8进制或16进制数if(!isdigit(c))//判断传入的C是否是0~9数字{return INADDR_INVALD;}if(c == '0')//8进制{base = 8,/*base相当于一个标志*/c = *++cp;//指针移动if(c == 'x' || c == 'X')base = 16,c = *++cp;//16进制}while( c = *cp++){if(isdigit(c)){if(base == 8 && c >= '8')//8进制中的数没有>=8的return INADDR_INVALD;value = value * base + (c - '0');}else if(base == 16 && isxdigit(c))value = (value << 4) | (c + 10 - (islower(c) ?'a' : 'A'));else break;digit = 1;//到这说明至少有一个数字if(c == '.')//遇到“.”的处理{if(!digit || p >= addr + 3 || value > 0xff)//0xff = 255return INADDR_INVALD;*p++ = (unsigned char)value;//将值保存到数组中,然后指针移动c = *cp;}else break;}}n = p - addr;//得到元素个数//解析完成,看是否有数字,检查尾部字节以及值的范围if(!digit || (value > range[n]) ||   (c != '\0' && !isspace(c)))   return INADDR_INVALD;//把地址的最后一部分保存到addr中for(i = 3;i >= n;i--,value >>= 8)addr[i] = (unsigned char)(value & 0xff);value = *(unsigned long *)addr;return value; } //下面是测试void main(){unsigned short host_s = 0x1234,net_s;unsigned long host_l = 0x12345678,net_l;char *addr_dec = "192.168.10.26",*p;struct in_addr addr;//char c;net_s = net_htons(host_s);net_l = net_htonl(host_l);printf("net byte order is :net_s = 0x%x,net_l = 0x%x\n",net_s,net_l);addr.s_addr = net_addr(addr_dec);p = net_ntoa(addr);printf("net addr is 0x%x,string addr is %s\n",addr.s_addr,p);//scanf("%c",&c);}



0 0
原创粉丝点击