v IPV4地址
我们使用的网络目前都是 IPv4 (IP version 4) 版本的,所以使用到的 IP 地址也是第 4 版本的,IPv6 版本的也有 ,不过先学好基础的嘛。所以,这个博客涉及到的所有的网络编程,都是基于 IPv4 的东东。在学习 IPv4 前,掌握 ip 地址相关的知识那是必须的必。
1. IP 地址
IPv4 地址,本质上是 32 位无符号整数。在 Linux 操作系统中,使用了 in_addr_t 类型来表示这样一个 4 字节的整数,它是由 typedef 定义的。
typedef uint32_t in_addr_t;
in_addr_t 这个类型保存的数据,到底是按本机字节序保存的,还是网络字节序保存的,这是不确定的!!!
为了解决此问题,Linux 又定义了一个新的结构体类型 struct in_addr,它明确的表示,它保存的 ip 地址就是网络字节序的!!!
struct in_addr {
in_addr_t s_addr;
}
如果说你传了一个本机字节序的 unsigned int 类型的整数给 in_addr 的 s_addr 成员,很抱歉,后面使用到该结构体的函数都会出错。
2. ip 地址表示方法
在第 1 节中也说了,ip 地址实际上就是一个 unsigned int 类型的整数。比方说接下来你和你同学说,你把你的 ip 地址配置成 0xc0a8a605 吧……你同学可能觉得你是从火星来的。。。
所以说,生活中使用整数来表示 ip 地址是相当不方便的,我们平时实际上都是用“点分十进制(dotted-decimal)”这种表示方法,比如 192.168.1.1 等等类似这样的。
点分十进制表示的 ip 地址和整数表示法之间的转换相当容易,就比如说 0xc0a8a605,先将其拆分成 4 个字节:c0.a8.a6.05,然后将 4 个部分的 16 进制数变成 10 进制,即 192.168.166.5,是不是很容易?
3. 制作in_addr类型的地址
比方我们需要把 192.168.166.5 保存成 in_addr 类型的地址,编写下面的代码就行了:
struct in_addr addr;
addr.s_addr = htonl(0xc0a8a605);
这样做看起来有点麻烦!每次都要自己先把点分十进制转成整数,然后再把整数转成网络字节序!
还好,Linux 提供一些函数,能够相当方便的帮我们把点分十进制的 ip 地址转换成 in_addr 类型。
4. 和IP地址转换相关的函数
下面这些函数中,aton 中的 a(address) 表示点分十进制的地址,n 表示网络字节序地址,ntoa 类似。
函数 lnaof 表示 local network address part of the Internet address in,即主机号。
函数 netof 表示 network number part of the Internet address in,即网络号。
#include
#include
#include
// 将点分十进制直接转换成 in_addr 类型,我们很喜欢这个函数
int inet_aton(const char *cp, struct in_addr *inp);
// 将点分十进制转换成 in_addr_t 类型,返回值保存的是网络字节序
in_addr_t inet_addr(const char *cp);
// 将点分十进制转换成 in_addr_t 类型,返回值保存的是本机字节序
in_addr_t inet_network(const char *cp);
// 将 in_addr 地址转换成点分十进制,注意这个函数不是线程安全的
char *inet_ntoa(struct in_addr in);
// 根据网络号和主机号制作 in_addr 类型地址
struct in_addr inet_makeaddr(int net, int host);
// 返回 ip 地址的主机号,返回的结果是本机字节序的
in_addr_t inet_lnaof(struct in_addr in);
// 返回 ip 地址的网络号,返回的结果是本机字节序的
in_addr_t inet_netof(struct in_addr in);
Ps:IP地址转换的函数还是挺多的,要好好的把这些程序都做一遍实验,好好敲一遍!
将点分十进制转换为网络字节序的函数有inet_addr 和 inet_aton。
但是,这两个函数是有区别的,inet_addr 函数如果出错会返回 -1,即 0xffffffff,因些地址 255.255.255.255 是无法转换的,虽然将此地址转换成的结果也是 0xffffffff,但是错误的 ip 地址比如 300.200.200.200 转换的结果也是 0xffffffff,所以 inet_addr 在不十分严谨的情况下才会使用。
inet_aton 是比较正式的,它单独使用返回值判断转换的地址是否有效,如果返回为 0,表示转换的地址是错误的。
6. 知识点总结
v in_addr_t 和 in_addr 的区别和联系
v in_addr 是网络字节序的
v in_addr_t 是什么字节序是不确定的
v 掌握相关的转换函数
v inet_addr 和 inet_aton 的区别