一、理论知识
二、主机字节序到网络字节序的转换函数
三、 inet_pton 函数与 htonl函数 的区别是什么?
四、实际编程中使用举例 (实际编程才是最重要,实践才是最好的学习方法)
一、理论知识
1、IP地址有哪几种表示形式?
博客01:https://zhidao.baidu.com/question/1829865613999852140.html
IP地址的三种表示方式是点分十进制(字符串类型)、网络字节序、主机字节序。
域名如“ www.baidu.com”并不是IP地址的表示方式,“192.168.0.1”属于点分十进制(这个是字符串的形式)。
(1)点分十进制(字符串类型)
点分十进制(Dotted Decimal Notation)全称为点分(点式)十进制表示法,是IPv4的IP地址标识方法。IPv4中用四个字节表示一个IP地址,每个字节按照十进制表示为0到255。点分十进制就是用4个从0~255的数字,来表示一个IP地址。如192.168.1.1(本质是一个字符串)。
(2)网络字节序(32位无符号整形unsigned int,网络地址,大头)
在网络传输中,TCP/IP协议在保存IP地址这个32位二进制数时,协议规定采用在低位存储地址中包含数据的高位字节的存储顺序(大头),这种顺序格式就被称为网络字节顺序格式。
在实际网络传输时,数据按照每32位二进制数为一组进行传输,由于存储顺序的影响,实际的字节传输顺序是由高位字节到低位字节的传输顺序。
为了使通信的双方都能够理解数据分组所携带的源地址、目的地址以及分组的长度等二进制信息,无论是主机还是路由器,在发送每一个分组以前,都必须将二进制信息转换为TCP/IP标准的网络字节顺序格式。网络字节顺序格式的地址不受主机、路由器类型的影响,它的表示是唯一的。
(3)主机字节序(主机地址)
主机字节序格式顾名思义,其IP地址的格式是和具体主机或者路由器相关的。对于不同的主机,在进行IP地址的存储时有不同的格式,比如对于 Motorola 68k系列主机,其HBO与NBO是相同的。而对于Intel x86系列,HBO与NBO则正好相反。
2、端口号port
short int 型 ,
二、主机字节序到网络字节序的转换函数
1、htonl(), ntohl(), htons(), ntohs() 函数
在C/C++写网络程序的时候,往往会遇到字节的网络顺序和主机顺序的问题。这是就可能用到htons(), ntohl(), ntohs(),htons()这4个函数。
网络字节顺序与本地字节顺序之间的转换函数:
htonl()–“Host to Network Long”
ntohl()–“Network to Host Long”
htons()–“Host to Network Short”
ntohs()–“Network to Host Short”
之所以需要这些函数是因为计算机数据表示存在两种字节顺序:网络字节顺序NBO(Network Byte Order)与主机字节顺序HBO(Host Byte Order)
2、头文件: #include <arpa/inet.h>
类型: int -> int
主机字节顺序 --> 网络字节顺序
uint16_t htons(uint16_t hostshort); 端口,即端口号port
uint32_t htonl(uint32_t hostlong); IP
网络字节顺序 --> 主机字节顺序
uint16_t ntohs(uint16_t netshort); 端口
uint32_t ntohl(uint32_t netlong); IP
3、IP地址转换函数 还有
(1)头文件 #include <arpa/inet.h>
(2)函数原型:
函数inet_pton原型 int inet_pton(int af, *const char src, void *dst);
函数inet_ntop原型 const char *inet_ntop(int af, *const void src, char *dst, socklen_t size);
(1)inet_pton中inet是一个前缀;p表示ip; n表示net;
函数作用:将 IP字符串类型 转换为 网络字节序。
三、 inet_pton 函数与 htonl函数 的区别是什么?
先给出答案:
相同点:这两个函数都可以将IP地址: 主机字节序 转换为 网络字节序
不同点:IP地址有三种表示方式:点分十进制(字符串类型)、网络字节序、主机字节序
数值型的ip地址转换用htonl,字符串类型(即点分十进制的形式)的用inet_pton
2、解决问题的方法:其实这种问题很简单,从函数原型的角度出发就可以很容易找到答案。
inet_pton函数原型 int inet_pton(int af, *const char src, void *dst);
第二个参数是字符型指针类型,指向一个字符串。即IP地址。IP地址以字符串形式表示的就是点分十进制。
htonl函数原型: uint32_t htonl(uint32_t hostlong);
运用示例:
u_long a = 0x12345678;
u_long b = htonl(a);//将主机的unsigned long 转为网络字节顺序(32位)
//u_long b = ntohl(a);//将网络字节顺序(32位)转为主机字节
四、实际编程中使用举例 (实际编程才是最重要,实践才是最好的学习方法)
1、实际代码
//1定义的时候定义成struct sockaddr_in
struct sockaddr_in servaddr, cliaddr;
// 2先把servaddr 结构体都置为0
bzero(&servaddr, sizeof(servaddr));
//3初始化结构体
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
//方法一:servaddr.sin_addr.s_addr 的初始化的方式一
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
//方法二:servaddr.sin_addr.s_addr 的初始化的方式二
//inet_pton(AF_INET,"192.168.42.100",&servaddr.sin_addr.s_addr);
2、INADDR_ANY 的理解 (开阔视野)
来源:https://baike.baidu.com/item/INADDR_ANY/1493998
INADDR_ANY就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”。 一般来说,在各个系统中均定义成为0值。
定义
例如MontiVista Linux中在/usr/include/netinet/in.h定义为:
/* Address to accept any incoming messages. */
#define INADDR_ANY ((in_addr_t) 0x00000000)
说明
一般情况下,如果你要建立网络服务器应用程序,则你要通知服务器操作系统:请在某地址 xxx.xxx.xxx.xxx上的某端口 yyyy上进行侦听,并且把侦听到的数据包发送给我。这个过程,你是通过bind()系统调用完成的。——也就是说,你的程序要绑定服务器的某地址,或者说:把服务器的某地址上的某端口占为已用。服务器操作系统可以给你这个指定的地址,也可以不给你。
如果你的服务器有多个网卡(每个网卡上有不同的IP地址),而你的服务(不管是在udp端口上侦听,还是在tcp端口上侦听),出于某种原因:可能是你的服务器操作系统可能随时增减IP地址,也有可能是为了省去确定服务器上有什么网络端口(网卡)的麻烦 —— 可以要在调用bind()的时候,告诉操作系统:“我需要在 yyyy 端口上侦听,所有发送到服务器的这个端口,不管是哪个网卡/哪个IP地址接收到的数据,都是我处理的。”这时候,服务器程序则在0.0.0.0这个地址上进行侦听。例如:
Proto Recv-Q Send-Q Local Address Foreign Address (state)
……
udp4 0 0 *.7913 .
udp4 0 0 .7911 .
tcp4 0 0 .ftp . LISTEN
……
……
以上这些是网络侦听的情况,其中Local Address 为 “.ftp”、“.7911”等,代表了服务程序绑定了服务器的所有网卡。
本文介绍了IP地址的三种表示形式:点分十进制、网络字节序和主机字节序,并详细讲解了网络字节序到主机字节序的转换函数htonl(), ntohl(), htons(), ntohs(),以及IP地址转换函数inet_pton和inet_ntop。同时,对比了inet_pton和htonl函数的区别,强调了实际编程中的应用和INADDR_ANY的理解。"
132593421,18852486,STM32单片机低功耗模式详解与代码示例,"['嵌入式硬件', 'STM32', '低功耗']
2854

被折叠的 条评论
为什么被折叠?



