【linux网络编程】网络字节序、地址转换
来源:互联网 发布:仿易企秀源码 编辑:程序博客网 时间:2024/06/02 03:41
网络字节序
故事的起源
“endian”这个词出自《格列佛游记》。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开,由此曾发生过六次叛乱,其中一个皇帝送了命,另一个丢了王位。我们一般将“endian”翻译成“字节序”,将 Big-Endian 和 Little-Endian 称作“大端格式”和“小端格式”。
字节序
字节序是指多字节数据的存储顺序,在设计计算机系统的时候,有两种处理内存中数据的方法:大端格式、小端格式。
小端格式(Little-Endian):将低位字节数据存储在低地址。
大端格式(Big-Endian):将高位字节数据存储在低地址。
举个简单的例子,对于整形 0x12345678,它在大端格式和小端格式的系统中,分别如下图所示的方式存放:
下面例子为确定主机的字节序:
#include <stdio.h>int main(int argc, char *argv){ unsigned int a = 0x11223344; unsigned char *p = (unsigned char *)&a; if (*p == 0x44) printf("Little endian...\n"); else printf("Big endian....\n"); return 0;}
输出结果为:
[root@localhost 9network]# ./a.out Little endian...[root@localhost 9network]#
网络上的数据流是字节流,对于一个多字节数值,在进行网络传输的时候,先传递哪个字节?也就是说,当接收端收到第一个字节的时候,它是将这个字节作为高位还是低位来处理呢?
网络字节序定义:收到的第一个字节被当作高位看待,这就要求发送端发送的第一个字节应当是高位。而在发送端发送数据时,发送的第一个字节是该数字在内存中起始地址对应的字节。可见多字节数值在发送前,在内存中数值应该以大端法存放。
所以,网络协议指定了通讯字节序:大端。只有在多字节数据处理时才需要考虑字节序,运行在同一台计算机上的进程相互通信时,一般不用考虑字节序,异构计算机之间通讯,需要转换自己的字节序为网络字节序。
字节序转换函数介绍
以下接口所需头文件:#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, char *argv[]){ int a = 0x11223344; short b = 0x1122; printf("htonl(%p): %p\n", a, htonl(a)); printf("htons(%p): %p\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
返回值:
成功:返回主机字节序的值
地址转换函数
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 <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>int main(void){ unsigned long ip = 0; unsigned char *p = NULL; inet_pton(AF_INET, "192.168.10.100", &ip); printf("ip = %lu\n", ip); p = (char*)&ip; printf("%d %d %d %d\n", *p, *(p + 1), *(p + 2), *(p + 3)); return 0;}
运行结果如下:
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 <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>int main(int argc, char **argv){ unsigned char ip[] = {192, 168, 10, 100}; char buf[16] = {0}; inet_ntop(AF_INET, ip, buf, 16); printf("buf: %s\n", buf); return 0;}
运行结果如下:
参考网址:http://blog.csdn.net/sunshine1314/article/details/2309655
- Linux 网络编程——网络字节序、地址转换
- Linux 网络编程——网络字节序、地址转换
- 【linux网络编程】网络字节序、地址转换
- Linux 网络编程——网络字节序、地址转换
- linux网络编程中的字节序转换
- linux网络编程中的字节序转换
- 六、Linux网络编程-socket、套接字地址结构、地址转换、字节序、套接字类型
- socket编程 -- 网络字节序、IP地址转换、sockaddr数据结构
- linux网络编程之socket(一):socket概述和字节序、地址转换函数
- linux网络编程之socket(一):socket概述和字节序、地址转换函数
- linux网络编程之socket(一):socket概述和字节序、地址转换函数
- linux网络编程之socket(一):socket概述和字节序、地址转换函数
- Linux网络编程之socket:socket与字节序以及地址转换函数
- linux网络编程之socket(一):socket概述和字节序、地址转换函数
- linux网络编程之socket(一):socket概述和字节序、地址转换函数
- linux网络编程之socket(一):socket概述和字节序、地址转换函数
- Linux网络编程03——字节序和地址转换
- linux网络编程之socket(一):socket概述和字节序、地址转换函数
- 布局
- 14级组队赛第一场3319 A simple water problem
- 解决window.open浏览器拦截的办法
- 第3周项目2 - 建设“顺序表”算法库(2)
- 45 个非常有用的 Oracle 查询语句
- 【linux网络编程】网络字节序、地址转换
- 宏拼接
- Hello JSP!——application对象
- C++析构函数为什么要为虚函数
- 利用Proxy Cache使Nginx对静态资源进行缓存
- hdoj-1215-七夕节【分解素因子+组合】
- 机器学习 实用技巧
- #研发解决方案介绍#基于ES的搜索+筛选+排序解决方案
- Qt入门学习——Qt 5 帮助文档的使用