网络字节序和主机字节序

转载 http://blog.csdn.net/msdnwolaile/article/details/50727653
http://blog.csdn.net/lianghe_work/article/details/45170285

我们都知道,如今的通讯方式已经趋向与多样化,异构通信(计算机软件(操作系统) + 计算机硬件(内核架构,ARM,x86)不同)也已经很普遍了,如,手机和电脑中的qq进行通信,,,

同时,在计算机设计之初,对内存中数据的处理也有不同的方式,(低位数据存储在低位地址处或者高位数据存储在低位地址处),然而,在通信的过程中(ISO/OSI模型和TCP/IP四层模型中),数据被一步步封装(然后加入信息首部),当传到目的段时,被一步步解封,然后获取数据

从上面我们可以看出,数据在传输的过程中,一定有一个标准化的过程,也就是说:从主机a到主机b进行通信,
a的固有数据存储-------标准化--------转化成b的固有格式

如上而言:a或者b的固有数据存储格式就是自己的主机字节序,上面的标准化就是网络字节序(也就是大端字节序)

a的主机字节序----------网络字节序 ---------b的主机字节序

主机字节序:
就是自己的主机内部,内存中数据的处理方式,可以分为两种:
大端字节序(big-endian):按照内存的增长方向,高位数据存储于低位内存中
小端字节序(little-endian):按照内存的增长方向,高位数据存储于高位内存中


网络上的数据流是字节流,对于一个多字节数值,在进行网络传输的时候,先传递哪个字节?也就是说,当接收端收到第一个字节的时候,它是将这个字节作为高位还是低位来处理呢?

网络字节序定义:收到的第一个字节被当作高位看待,这就要求发送端发送的第一个字节应当是高位。而在发送端发送数据时,发送的第一个字节是该数字在内存中起始地址对应的字节。可见多字节数值在发送前,在内存中数值应该以大端法存放。

所以,网络协议指定了通讯字节序:大端。只有在多字节数据处理时才需要考虑字节序,运行在同一台计算机上的进程相互通信时,一般不用考虑字节序,异构计算机之间通讯,需要转换自己的字节序为网络字节

但是,如何知道我们的主机是那一种的呢???这个我们可以通过程序来进行验证:

#include <stdio.h>  
#include <arpa/inet.h>   
int main(){  
     unsigned long a = 0x12345678;  
     unsigned char *p = (unsigned char *)(&a);  
     printf("主机字节序:%0x    %0x   %0x   %0x\n",  p[0], p[1], p[2], p[3]);  
     unsigned long b = htonl(a);  //将主机字节序转化成了网络字节序        
     p = (unsigned char *)(&b);  
     printf("网络字节序:%0x    %0x   %0x   %0x\n",  p[0], p[1], p[2], p[3]);  //16进制输出
     return 0;  
}  

运行结果:

可以看到我的当前主机是:小端字节序

#include <arpa/inet.h>  
  
uint32_t htonl(uint32_t hostlong);  
  
uint16_t htons(uint16_t hostshort);  
  
 uint32_t ntohl(uint32_t netlong);  
  
uint16_t ntohs(uint16_t netshort);

h是主机host,n是网络net,l是长整形long,s是短整形short,所以上面这些函数还是很好理解的

#include <stdio.h>  
#include <arpa/inet.h>  
  
int main()  
{  
        struct in_addr ipaddr;  
        unsigned long addr = inet_addr("192.168.1.100");  
        printf("addr = %u\n", ntohl(addr));  
  
        ipaddr.s_addr = addr;  
        printf("%s\n", inet_ntoa(ipaddr));        
        return 0;         
} 

运行结果:



值得注意的是:

in_addr_in inet_addr(const char *strptr);

inet_addr的参数是一个:点分十进制字符串,返回的值为一个32位的二进制网络字节序的IPv4地址,不然的话就是:INADDR_NONE
而返回值为:in_addr_t:IPv4,一般为uint32_t
所以也可以定义为:unsigned long

char * inet_ntoa(struct in_addr inaddr);

参数是一个结构体,所以要调用必须先定义一个结构体。
将网络地址转换成"."点隔的字符串格式。

以下接口所需头文件:#include <arpa/inet.h>

uint32_t htonl(uint32_t hostint32);

功能:
将 32 位主机字节序数据转换成网络字节序数据

参数:
hostint32:需要转换的 32 位主机字节序数据,uint32_t 为 32 为无符号整型

返回值:
成功:返回网络字节序的值

uint16_t htons(uint16_t hostint16);

功能:
将 16 位主机字节序数据转换成网络字节序数据

参数:
hostint16:需要转换的 16 位主机字节序数据,uint16_t,unsigned short int

返回值:
成功:返回网络字节序的值

测试示例:

#include <stdio.h>  
#include <arpa/inet.h>  
  
int main(int argc, charchar *argv[])  
{  
    int a = 0x01020304;  
    short int b = 0x0102;  
      
    printf("htonl(0x%08x) = 0x%08x\n", a, htonl(a));  
    printf("htons(0x%04x) = 0x%04x\n", b, htons(b));  
      
    return 0;  
}  

运行结果如下:

uint32_t ntohl(uint32_t netint32);

功能:
将 32 位网络字节序数据转换成主机字节序数据

参数:
netint32:待转换的 32 位网络字节序数据,uint32_t,unsigned int

返回值:
成功:返回主机字节序的值

uint16_t ntohs(uint16_t netint16);

功能:
将 16 位网络字节序数据转换成主机字节序数据

参数:
netint16:待转换的 16 位网络字节序数据,uint16_t,unsigned short int

返回值:
成功:返回主机字节序的

三、地址转换函数以下接口所需头文件:#include <arpa/inet.h>

int inet_pton(int family, const char *strptr, void *addrptr);

功能:
将点分十进制数串转换成 32 位无符号整数

参数:
family:协议族( AF_INET、AF_INET6、PF_PACKET 等 ),常用 AF_INET
strptr:点分十进制数串
addrptr:32 位无符号整数的地址

返回值:
成功返回 1 、 失败返回其它
测试示例:

#include <stdio.h>  
#include <arpa/inet.h>  
int main()  
{  
    char ip_str[]="172.20.223.75";  
    unsigned int ip_uint = 0;  
    unsigned charchar *ip_p = NULL;  
  
    inet_pton(AF_INET,ip_str,&ip_uint);  
    printf("in_uint = %d\n",ip_uint);  
      
    ip_p = (charchar *)&ip_uint;  
    printf("in_uint = %d,%d,%d,%d\n",*ip_p,*(ip_p+1),*(ip_p+2),*(ip_p+3));  
  
    return 0;  
}  

运行结果如下:

inet_ntop

const char *inet_ntop( int family, 
                       const void *addrptr,   
                       char *strptr, 
                       size_t len );

功能:
将 32 位无符号整数转换成点分十进制数串

参数:
family:协议族( AF_INET、AF_INET6、PF_PACKET 等 ),常用 AF_INET
addrptr:32 位无符号整数
strptr:点分十进制数串
len:strptr 缓存区长度

len 的宏定义
#define INET_ADDRSTRLEN   16  // for ipv4
#define INET6_ADDRSTRLEN  46  // for ipv6

返回值:
成功:则返回字符串的首地址
失败:返回 NULL

测试示例:

#include <stdio.h>  
#include <arpa/inet.h>  
int main()  
{  
    unsigned char ip[] = {172,20,223,75};  
    char ip_str[16] = "NULL";  
  
    inet_ntop(AF_INET,(unsigned intint *)ip,ip_str,16);  
    printf("ip_str = %s\n",ip_str);  
  
    return 0;  
}  

运行结果如下:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 1) 物理层定义了网络的物理结构、传输的电磁标准、Bit流的编码及网络的时间原则。2)数据链路层在两个主机上建立数...
    吃肉666阅读 1,859评论 0 1
  • 1.1 网络常识 1)网络的7层网络协议 ISO按照逻辑划分出来7层网络协议 应用层:和应用程序打交道的,进行数据...
    vera姐姐阅读 470评论 0 1
  • 一、网络中进程之间如何通信 首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一...
    向阳的向日葵花阅读 2,005评论 0 4
  • socket编程 网络通信, 首先那些七层模型等概念, 直接百度或谷歌查询, 小的不才, 不如别人总结的. 不过那...
    wulegekong阅读 6,818评论 2 12
  • 1.解决识别唯一进程的原理 ,网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主...
    傻傻小萝卜阅读 2,671评论 0 12