首页 > 系统相关 >Linux 网络编程——网络字节序、地址转换

Linux 网络编程——网络字节序、地址转换

时间:2022-09-28 20:03:33浏览次数:55  
标签:字节 int ip 网络 unsigned char Linux include


网络字节序

故事的起源

“endian”这个词出自《格列佛游记》。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开,由此曾发生过六次叛乱,其中一个皇帝送了命,另一个丢了王位。


我们一般将“endian”翻译成“字节序”,将 Big-Endian 和 Little-Endian 称作“大端格式”和“小端格式”。


字节序

字节序是指多字节数据的存储顺序,在设计计算机系统的时候,有两种处理内存中数据的方法:大端格式、小端格式。


小端格式(Little-Endian):将低位字节数据存储在低地址。
大端格式(Big-Endian):将高位字节数据存储在低地址。

Linux 网络编程——网络字节序、地址转换_网络编程


举个简单的例子,对于整形 0x12345678,它在大端格式和小端格式的系统中,分别如下图所示的方式存放:

Linux 网络编程——网络字节序、地址转换_字节序_02

下面例子为确定主机的字节序:


#include <stdio.h>

int main(int argc, char *argv[])
{
unsigned int a = 0x12345678;
unsigned char *p = (unsigned char *)&a; //只取一个字节
if(0x12 == *p){
printf("Big-Endian\n");
}else if(0x78 == *p){
printf("Little-Endian\n");
}

return 0;
}


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

 

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


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


字节序转换函数介绍

以下接口所需头文件:#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 = 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;
}


运行结果如下:

Linux 网络编程——网络字节序、地址转换_网络字节序_03


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 char *ip_p = NULL;

inet_pton(AF_INET,ip_str,&ip_uint);
printf("in_uint = %d\n",ip_uint);

ip_p = (char *)&ip_uint;
printf("in_uint = %d,%d,%d,%d\n",*ip_p,*(ip_p+1),*(ip_p+2),*(ip_p+3));

return 0;
}


运行结果如下:

Linux 网络编程——网络字节序、地址转换_字节序_04


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 int *)ip,ip_str,16);
printf("ip_str = %s\n",ip_str);

return 0;
}


运行结果如下:

Linux 网络编程——网络字节序、地址转换_网络编程_05




标签:字节,int,ip,网络,unsigned,char,Linux,include
From: https://blog.51cto.com/u_3002289/5720761

相关文章

  • Linux 进程调度浅析
    概述操作系统要实现多进程,进程调度必不可少。有人说,进程调度是操作系统中最为重要的一个部分。我觉得这种说法说得太绝对了一点,就像很多人动辄就说“某某函数比某某函数效率......
  • Linux 网络编程——原始套接字实例:发送 UDP 数据包
    以太网报文格式:IP报文格式:UDP报文格式:校验和函数:/*******************************************************功能:校验和函数参数:buf:需要校验数据的首地址nword:......
  • Linux磁盘管理与文件系统
    了解磁盘盘片:硬盘有多个盘片,每盘片2面磁头:每面一个磁头扇区:盘片被分为多个扇形区域,每个扇区存放512字节的数据,硬盘的最小存储单位磁道:同一盘片不同半径的同心圆,......
  • 如何在linux下检测(自身)IP冲突
    最近遇到一个需求,或者说是一个用户现场问题。我们设备先安装,设置dhcp模式获取ip进行联网,后来又安装了其他设备,但该设备是手动设置的静态ip地址,正好与我们设备冲突......
  • Linux make编译
    安装问题linux编译流程linux开发部分一般来说著名的linux系统基本上分两大类:RedHat系列:Redhat、Centos、Fedora等Debian系列:Debian、Ubuntu等RedHat系列常见的......
  • Linux下Docker方式在线安装Jenkins容器
    一、Docker在线安装https://www.cnblogs.com/dabao150114/p/16739213.html二、portainer容器在线安装https://www.cnblogs.com/dabao150114/p/16739217.html三、安装Je......
  • 2022 ICPC 网络预选赛(9.25)
    真容易颓。E构造一个序列\(a_1\)已经确定使得\((a_i,a_{i-1})=1,a_i>1\)求整个序列最大值。容易知道\(a_2\)是与\(a_1\)互质的最小质数若是2接下填3,2,3,2,3即可.若......
  • Linux下Jenkins离线安装(war包)
    1、下载Jenkins.war包地址:https://mirrors.jenkins.io/war-stable/2.346.3/2、将Jenkins.war包上传到/usr/local/tomcat/webapps3、浏览器访问:http://192.168.150.128......
  • Linux下Gitlab服务器(docker安装)
    一、Docker在线安装https://www.cnblogs.com/dabao150114/p/16739213.html二、portainer容器在线安装https://www.cnblogs.com/dabao150114/p/16739217.html三、GitLab......
  • Linux下Docker在线安装
    Docker在线安装1、安装Docker(1).安装yum-utils软件包(提供yum-config-manager实用程序)[root@localhost]#sudoyuminstall-yyum-utils(2).设置稳定的存储......