socket学习---地址端口转换
前言
本次博客不是介绍socket,而是我讲一下socket当中地址、端口的转换函数。今天本来在开心的搓muduo网络库,看到它需要实现InetAddrss类,类的作用是将sockaddr的初始化封装起来,看到这里,我说这不简单吗,随便写一下就行,但是当我真正开始写的时候才发现,我好多api都忘记了,比如如何将sockaddr_in.sin_addr.s_addr转换为字符串,或者如何将字符串转化为s_addr,所以这篇博客我准备复习一下地址端口的转化。
一、sockaddr_in介绍
所在头文件
include <netinet/in.h>
结构体定义
typedef uint16_t in_port_t;
typedef uint32_t in_addr_t;
struct in_addr{
in_addr_t s_addr;
};
struct sockaddr_in{
in_port_t sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[...];//这部分是用来适配sockaddr大小的,暂时不管
};
以上就是sockaddr_in的定义,首先,port就是一个2字节无符号整数,而端口号正好也这么大;然后是s_addr,看起来套了几层很麻烦,但是其实用起来很简单,就是拿一个32位大小的空间记录ipv4地址(ipv4大小就是32位),那为什么要搞这么奇怪?这其实是历史原因,大家知道怎么用就行了(我忘了是具体是什么原因了~~~)。sin_zero是用来使其大小和sockaddr变得相同,同时便于扩展。
二、网络字节序
通常计算机分为大端和小端,大端是指数据高位字节存在低地址,小端相反,高位字节存在高地址,举个例子,有个32位整数的16进制表示为:0x01020304,那么在大端系统中,地址从低到高存储的内容依次为:01 02 03 04,而在小端:04 03 02 01。但是在网络传输中,信息是以字节传输,两台大小端不同的机器也会使用字节传输,那么传输的时候就要统一大小端,而sockaddr_in是会存在于发送的信息中的,所以需要统一大小端,所以接下来介绍如何统一大小端。
三、统一大小端
//将32位长整型转化位网络字节序形式
uint32_t htonl(uint32_t hostlong);
//将16位短整型转化位网络字节序形式
uint16_t htons(uint16_t hostshort);
//将32位网络字节序转化位本地大小端形式
uint32_t ntohl(uint32_t netlong);
//将16位网络字节序转化位本地大小端形式
uint16_t ntohs(uint16_t netshort);
struct sockaddr_in addr;
memset(&addr,0,sizeof(addr));
addr_.sin_family = AF_INET;
addr_.sin_port = ::htons(port);//port:uint16_t
addr_.sin_addr.s_addr = htonl(ip); //ip:uint32_t
四、字符串与端口、地址之间的转化
//将点分十进制IP转化为网络字节序存放在addr中,并返回该网络字节序对应的整数。
int inet_aton(const char *cp, struct in_addr *inp);
//将点分十进制IP转化为网络字节序
in_addr_t inet_addr(const char *cp);
//将点分十进制IP转化为主机字节序
in_addr_t inet_network(const char *cp);
//网络字节序的地址转化为字符串,但是不推荐,因为不可重入
char *inet_ntoa(struct in_addr in);
/*
用得很少
struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host);
in_addr_t inet_lnaof(struct in_addr in);
in_addr_t inet_netof(struct in_addr in);
*/
/*
af:地址族。
src:点分十进制字符串格式的IP地址(如 "192.168.1.1" 或 "2001:db8::1")。
dst:用于存储网络字节序的二进制格式的 IP 地址,通常是 struct in_addr 或 struct in6_addr。
返回值
1:成功转换。
0:输入字符串格式非法。
-1:出错,并将错误代码存储在 errno 中。
作用
将字符串格式的 IP 地址转换为网络字节序的二进制格式。
支持 IPv4 和 IPv6 地址。
*/
int inet_pton(int af, const char *src, void *dst);
/*
参数
af:地址族
src:网络字节序的二进制格式 IP 地址(struct in_addr 或 struct in6_addr)。
dst:输出字符串缓冲区,存储转换后的字符串格式 IP 地址。size:dst 缓冲区的大小。
返回值
成功时返回指向输出字符串的指针。出错时返回 NULL,并设置 errno。
作用
将网络字节序的二进制格式 IP 地址转换为字符串格式。
*/
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);