Linux高性能服务器编程 网络字节序本地字节序点分十进制转换函数总结 两种初始化socket并bind的步骤
网络字节序本地字节序点分十进制转换函数总结&&两种初始化socket并bind的步骤
看完这些转换可以去看初始化socket的步骤,会印象更加深刻一些
##1.网络字节序、本地字节序和点分十进制的数据长啥样
1.点分十进制
常用来表示ip,就是192.168.120.139这样的字符串
2.本地字节序(主机字节序)和网络字节序
字节存储顺序主要分为大端序(Big-endian)和小端序(Little-endian),区别如下
- Big-endian:高位字节存入低地址,低位字节存入高地址
- Little-endian:低位字节存入低地址,高位字节存入高地址
例如,将12345678h
写入1000h
开始的内存中,以大端序和小端序模式存放结果如下:
现代 PC 大多采用小端字节序,因此小端字节序
又称为主机字节序
;
而在两台不同字节序的主机之间传递数据时,发送端总是把要发送的数据转化成大端字节序
数据后再发送,因此大端字节序也被称为网络字节序
。
3.重点:
1.凡是和socket相关的都要转为网络字节序
2.ip如果是本地字节序或点分十进制的字符串就要转为网络字节序
3.port如果是本地字节序就要转为网络字节序
4.我们也不用去管自己的机器到底是大端还是小端,把输进来的全都转成大端就行了
2.网络字节序本地字节序点分十进制转换函数
1.主机(本地)转网络字节序–常用
用来转换端口号或ip
长整型用来转换ip,短整型用来转换端口号
1 | include <netinet/in.h> |
2.网络转主机(本地)字节序
ip的一般不用,想要查看端口是多少的话就查查端口
1 | //用于ip |
3.点分十进制转网络字节序
用于ip
1 |
|
- 函数原型
int inet_pton(int af, const char *src, void *dst);
- 参数含义
af
参数:- 代表地址族(Address Family)。它用于指定要转换的 IP 地址所属的协议族。
- 常见的值是
AF_INET
(用于 IPv4 地址)和AF_INET6
(用于 IPv6 地址)。这告诉函数按照哪种网络协议版本的规则来进行地址转换。
src
参数:- 是一个常量字符串指针(
const char *
),它指向要进行转换的 IP 地址的字符串表示形式。 - 对于
AF_INET
,这个字符串应该是点分十进制(如"192.168.1.1"
)的 IPv4 地址格式。对于AF_INET6
,它应该是符合 IPv6 地址规范的字符串格式(如"2001:0db8:85a3:0000:0000:8a2e:0370:7334"
)。
- 是一个常量字符串指针(
dst
参数:- 是一个指针,用于存储转换后的二进制 IP 地址。
- 当
af
为AF_INET
时,dst
通常指向一个struct in_addr
类型的结构体,转换后的 32 位 IPv4 地址会存储在这个结构体的s_addr
成员中。当af
为AF_INET6
时,dst
通常指向一个struct in6_addr
类型的结构体,用于存储转换后的 IPv6 地址。
3.返回值
- 如果转换成功,函数返回
1
。 - 如果输入的
src
字符串不是合法的 IP 地址格式(对于指定的af
),函数返回0
。 - 如果发生其他错误(如
af
参数指定了不支持的地址族等),函数返回-1
。
4.网络字节序转点分十进制
常用于想要查看与socket绑定的ip地址时使用
1 | char* inet_ntoa( struct in_addr in ); |
char *inet_ntoa(struct in_addr in);
- 参数
in
:是一个struct in_addr
类型的结构体,其中存储了网络字节序的 IPv4 地址。这个结构体只有一个成员s_addr
,用于存放 32 位的 IPv4 地址。
- 参数
inet_ntop
函数原型:const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
参数
af
:指定地址族,如AF_INET
(IPv4)或AF_INET6
(IPv6)。参数
src
:是一个指向存储网络字节序 IP 地址的指针。对于 IPv4,它指向struct in_addr
类型结构体中的s_addr
成员;对于 IPv6,它指向struct in6_addr
类型结构体。参数
dst
:是一个字符数组,用于存储转换后的 IP 地址字符串。参数
size
:是dst
字符数组的大小,用于防止缓冲区溢出。返回值:如果成功,返回
dst
(指向存储转换后 IP 地址字符串的字符数组的指针);如果失败,返回NULL
。例子:
1 | printf("client ip:%s port:%d\n", |
打印ip和端口号
3.两种初始化socket并bind的步骤
1.黑马中的
1 | int listenfd=0,connfd=0; |
1.调用socket创建一个socket(所有这类函数都把它自身和错误处理封装为类似Socket这种类型了)
2.命名socket,就是把一个sockaddr_in的内部成员赋值后转为sockaddr *绑定到socket上
2.1 sockaddr_in 成员赋值
1.地址族 这是一个宏,是固定的
2.端口号 要用网络字节序来表示 htos是本地字节序转网络字节序,作用是不管本地字节序是大端还是小端全都转为大端
3.ip地址 赋值 除了inet_aton和inet_pton(这两个是将点分十进制的ip转为网络字节序),还可以用上面的写法 ,即用INADDR_ANY的写法
INADDR_ANY
的含义INADDR_ANY
是一个特殊的常量,用于网络编程中表示本地机器的任意网络接口地址。它并不是一个真正的 IP 地址码,而是一个用于套接字绑定操作的占位符概念。- 从数值上来说,在 IPv4 环境下,
INADDR_ANY
通常被定义为0
(十六进制表示为0x00000000
)。这个值并不对应特定的字节序(如本地字节序或网络字节序)下的有效 IP 地址。
- 字节序和
INADDR_ANY
的关系- 当将
INADDR_ANY
用于网络编程中的函数(如bind
函数)时,它的处理方式与字节序转换函数有关。 - 例如,在代码中常常会看到
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
这样的语句。这里htonl
函数将INADDR_ANY
(其值为0
)从主机字节序转换为网络字节序。 - 因为在网络通信中,
sockaddr_in
结构体中的sin_addr.s_addr
字段需要存储网络字节序的 IP 地址,所以即使INADDR_ANY
本身的值很简单(为0
),也需要进行字节序转换操作,以符合网络协议对数据格式的要求。
- 当将
- 实际用途
- 当服务器程序使用
bind
函数将套接字绑定到INADDR_ANY
时,它表示服务器愿意接受来自本地机器上任何可用网络接口的连接请求。这对于服务器在多宿主主机(有多个网络接口,每个接口有不同的 IP 地址)上运行非常有用,因为服务器不需要指定一个特定的 IP 地址来接收连接,而是可以监听所有的本地 IP 地址。
- 当服务器程序使用
2.2 将sockaddr_in强转为sockaddr *,因为bind之类的函数只接受这类参数,不接受sockaddr_in
3.bind进行绑定
2.linux高性能服务器中的,可以在命令行中输入
1 | if(argc<=2) |
这个是通过命令行参数来进行创建socket的,其实就是通过argv数组把ip和端口号传了进来
ip传入的时候就是点分十进制,端口号传入的时候就是本地字节序
举例:
1 | ./sever 192.168.120.139 1234 |
./sever 要运行的服务器程序
192.168.120.139 点分十进制的ip
1234 本地字节序的port
步骤:
1.调用socket创建一个socket(所有这类函数都把它自身和错误处理封装为类似Socket这种类型了)
2.命名socket,就是把一个sockaddr_in的内部成员赋值后转为sockaddr *绑定到socket上
2.1 sockaddr_in 成员赋值
1.地址族 这是一个宏,是固定的
2.端口号 要用网络字节序来表示。htos是本地字节序转网络字节序,作用是不管本地字节序是大端还是小端全都转为大端
3.ip地址 赋值 除了inet_aton和inet_pton(这两个是将点分十进制的ip转为网络字节序),还可以用上面的写法 ,即用INADDR_ANY的写法
INADDR_ANY
的含义INADDR_ANY
是一个特殊的常量,用于网络编程中表示本地机器的任意网络接口地址。它并不是一个真正的 IP 地址码,而是一个用于套接字绑定操作的占位符概念。- 从数值上来说,在 IPv4 环境下,
INADDR_ANY
通常被定义为0
(十六进制表示为0x00000000
)。这个值并不对应特定的字节序(如本地字节序或网络字节序)下的有效 IP 地址。
- 字节序和
INADDR_ANY
的关系- 当将
INADDR_ANY
用于网络编程中的函数(如bind
函数)时,它的处理方式与字节序转换函数有关。 - 例如,在代码中常常会看到
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
这样的语句。这里htonl
函数将INADDR_ANY
(其值为0
)从主机字节序转换为网络字节序。 - 因为在网络通信中,
sockaddr_in
结构体中的sin_addr.s_addr
字段需要存储网络字节序的 IP 地址,所以即使INADDR_ANY
本身的值很简单(为0
),也需要进行字节序转换操作,以符合网络协议对数据格式的要求。
- 当将
- 实际用途
- 当服务器程序使用
bind
函数将套接字绑定到INADDR_ANY
时,它表示服务器愿意接受来自本地机器上任何可用网络接口的连接请求。这对于服务器在多宿主主机(有多个网络接口,每个接口有不同的 IP 地址)上运行非常有用,因为服务器不需要指定一个特定的 IP 地址来接收连接,而是可以监听所有的本地 IP 地址。
- 当服务器程序使用
2.2 将sockaddr_in强转为sockaddr *,因为bind之类的函数只接受这类参数,不接受sockaddr_in
3.bind进行绑定