1. IP 协议
基本概念:
主机:配有 IP 地址,但是不进行路由控制的设备
路由器:即配有 IP 地址,又能进行路由控制
节点:主机和路由器的统称
IP 协议报头格式
1) 4 位版本:实际上只有两个取值(4 -> IPv4(主流)、6 -> IPv6)
2) 4 位首部长度:IP 协议报头也是变长的(0 -> 15,实际上报头长度 * 4,例如:当 15 时,报头长度就是 60)
3) 8 位服务类型(TypeOfService):3 位优先权字段(已经弃用),4 位 TOS 字段,1 位保留字段(必须置为 0)
4 位 TOS 分别表示:最小延时,最大吞吐量、最高可靠性、最小成本,这四者相互冲突,只能选择一个,对于 ssh/telnet 这样的应用程序,最小延时比较重要;对于 ftp 这样的程序,最大吞吐量比较重要
最小延时:数据从 A 到 B 的时间消耗最短
最大吞吐量:数据从 A 到 B 单位时间内,传输的数量更多
最高可靠性:IP 协议并不像 TCP 那样有严格的可靠性,但是 IP 的一些机制也会影响到丢包的概率
最小成本:设备上消耗的资源较少
4) 16 位总长度(字节数):IP 数据报的长度,UDP 也是 16 位(2 个字节),但是 IP 并不是和 UDP 一样只能传输 64KB 的数据
IP 协议内置了拆包组包机制,单个 IP 数据报确实没法超过 64KB,但是不代表 IP 协议不能传输超过 64KB 的数据,IP 协议会自动把大的数据包拆成多个 IP 数据包携带数据,到接收方再进行拼装
5) 16 位标识 / 3 位标志 / 13 位片偏移
IP 协议会自动拆包,同一个载荷的数据会被分成多份,交给多个 IP 数据来携带,多个 IP 数据包,16 位标识是相同的数值
13 位片偏移决定组包的时候数据包的位置(网络中存在后发先至)
3 位标志位,只有 2 个有效(剩下一个保留),其中一个表示这个包是否需要组包(是否是拆包的一部分),另一个表示当前包是否是组包中的最后一个单位
tip:面试题:如果像使用 UDP 实现传输超过 64KB 的数据,如何做?
实现方案:参考 IP,应用层编写代码时,引入标识(id),约定标识相同的数据就应该进行组包
引入片偏移,约定组包时数据的先后顺序
引入标志位,区分是否需要组包,标识一个包
6) 8 位生存时间(TTL)一个数据包在网络中最多存活时间,假设构造一个 IP 数据包,目的 IP 写错了,写成不存在的 IP,如果让这样的数据包无限传输,就会消耗很多网络的资源,TTL 约定了传输时间的上限,达到上限之后,数据包就会自动被丢弃掉
TTL 的单位不是 s 或 min,而是 “次数”,指的是经过路由器转发的次数
发送一个 IP 数据包的时候,会有一个初始的 TTL的值(32、64、128...),数据包每次经过一个路由器转发,TTL 就会 -1(经过交换机不减),一旦 TTL 减到 0,此时这个数据包就会被当前的路由器直接丢弃掉
tip:正常情况下,64 这样的 TTL 是非常充裕的(类似于 “六度空间理论”)
7) 8 位协议:IP 数据包中,携带的载荷是哪种传输层协议的数据包
通过这里的不同数值,感知到,接下来要把数据交给 TCP 解析,还是 UDP 解析,或是其他协议解析....(类似于 TCP/UDP 报头中的 “端口号”)
8) 16 位首部检验和:验证数据在传输中是否出错(只针对首部,IP 报头部分),载荷部分 TCP/UDP 都有自己的校验和了
9) 32 位源 IP 地址/32 位目的 IP 地址:IP 数据包中最关键的信息,数据包从哪里来,到哪里去
IP 地址是 32 位的整数,是一个很大的数字,不方便人进行阅读和理解,因此将 32 位(4字节)通过 3 个圆点分隔开,每个部分是一个字节,范围 0~255,称其为 “点分十进制”
IP 地址,用来标识网络上的一个设备,我们期望 IP 地址是唯一的,而 32 位表示的数据范围:0 ~ 42亿9千万,这样的数字放到现在,不一定够用了
为了解决 IP 不够用的问题,有以下方案
方案一:动态分配 IP 地址,一个设备上网就分配,不上网就先不分配
方案二:NAT 网络地址转换,以一当千,使用一个 IP 代表一大波设备
将 IP 地址分成两大类:
1. 内网 IP / 私网 IP(10.* 172.16.* - 172.31.* 192.168.*)(重点!)
2. 外网 IP / 公网 IP
NAT 网络地址转换:一个设备在进行上网的时候,IP 数据包中的 IP 地址就会被 NAT 设备(通常就是路由器)进行自动的修改
网络访问分为以下几种情况
1) 同一个局域网内,主机 A 访问主机 B,不会涉及到 NAT 机制
2) 公网上的设备 A,访问公网上的设备 B,不会涉及到 NAT 机制
3) 一个局域网中的主机 A 访问另一个局域网中的主机 B,NAT 机制中是不允许的
4) 局域网内部的设备 A 访问公网上的设备 B,NAT 机制主要就是针对此情况生效的
在网络通信中,不仅仅只有 IP 信息,还有端口号,端口号本来是区分一个主机上不同的应用程序的,在 NAT 中就可以用于不同主机上不同的应用程序
tip:由于客户端的源端口是操作系统随机分配的空闲端口,那么两台电脑的端口都是 1234 的概率是 1/60000
NTA 机制的缺点:
网络环境太复杂了,在 NTA 替换过程中,每一层路由器都需要维护映射关系,每次转发数据,都需要查询映射关系,这些都是开销
解决方案三:IPv6(从根本上解决 IP 地址不够用的问题)
IPv4 使用 32 位 4 个字节表示 IP 地址;IPv6 使用 128 位 16 个字节表示 IP 地址
16个字节表示的 IP 地址的数量可不是 4 个字节的 IP 地址的 4 倍,他是一个指数关系
2^128 = 2^32 * 2^32 * 2^32 * 2^32,IPv6 的地址空间非常大,足够给地球上的每一粒沙子都分配一个唯一的 IPv6 地址
地址管理、网段划分
IP 地址是一个 32 位整数,将其一分为二,左半部分为网络号,右半部分为主机号
需要通过 “子网掩码” 来区分具体哪些是网络号,哪些是主机号
网络中规定:
同一个局域网中的设备,网络号必须相同,主机号必须不同
两个相邻的局域网中,网络号必须不同
ABCDE 五类网络
除了子网掩码的方案,还有一种 ABCDE 五类网络的方案,不过这是上古时期的网络划分方式了,目前只存在于教科书上了
特殊的 IP 地址
1. 主机号全为 0(二进制)
此时这个 IP 就是表示当前网段(相当于网络号),因此给局域网中的某个设备分配 IP 地址时,不能把主机号设为全 0
2. 主机号全为 1(二进制)
比如子网掩码是 255.255.255.0 的 IP 地址:192.168.0.255(其中主机号 255 就是 1111 1111)
往这个 IP 地址上发送数据包,相当于给整个局域网中所有的设备都发了一次数据包(特殊情况下的特殊解决方案)
平常看到的“业务上的广播”都是通过应用层编写代码来实现的,而不是借助广播 IP,例如:
以 cctalk 为例,cctalk 服务器会维护出很多的 “教室信息”,每个直播间就是一个教室,一个教室里会涉及到很多同学(教室中包含所有同学的数据),此时当直播间的老师进行一段直播时,画面和声音就会发给 cctalk 服务器对应的教室这里,cctalk 服务器就会根据教室中同学的列表(依次遍历每个列表元素),把数据发送过去
真正用到广播 IP 的例子:手机与电视之间投屏,当手机与电视处于同一个局域网时,手机上基于广播 IP 来知道局域网中有多少个设备允许投屏
手机触发投屏按钮的时候,往对应的广播 IP 上发送一个数据包(UDP,TCP 不支持广播,只支持一对一)
如果收到这个数据包的设备不具有投屏功能就无响应
如果收到这个数据包的设备具有投屏功能,就会返回一个响应,告知其是一个什么设备,IP 是多少
3. 127.*
环回 IP(loopback)
自发自收,给这个 IP 发一个数据,设备就会从这个 IP 上再收到同一个数据(自己发给自己)
日常中写的网络通信大多数情况都是为了跨主机通信,在这之前需要先自行测试,一台主机测试自己测客户端和服务器之间能否正常交互,就使用到环回 IP
一般使用的环回 IP 就是 127.0.0.1,虽然其他 127 开头的 IP 也是可以的,但是很少见
简单了解 “路由选择” 的大概流程
网络是复杂的网状结构,从一个节点到另一个节点之间可能存在很多条路线,就类似于生活中的交通网(公路网)
举个例子:假设我们现在要从陕西科技大学(北郊)前往西安邮电大学(南郊),我们可以打开地图软件,它会提供给我们多条线路进行选择
tip:地图软件的线路选择和 IP 协议的路由选择是有本质去别的
在地图软件中,它能够知道路线的全貌,能给我们计算出“最优解”(用时最短、成本最低、最少换乘等等)
而每个路由器无法知道整个网络结构的全貌,只能知道其中的一小部分(每个路由器只知道它附近的设备是怎样的情况),无法得到“最优解”,只能得到“较优解”
路由选择的基本情况和下例类似:
上述问路的过程就和 IP 协议路由选择非常相似,上述的 ABCDE 这几个路人就相当于路由器,每个路由器都不知道整体网络的全貌,但是能够知道其中的一部分
路由表(路由器内部维护的重要的数据结构),路由表类似于 hash 一样,key 相当于 IP 地址(网络号),value 就是对应的网络接口(往哪个方向走)
IP 数据包到达路由器,就需要进行路由表查表操作,查一查 IP 数据包中的目的 IP 在路由表中是否存在,如果查到了,自然按照路由表指向的方向继续转发即可,如果没查到,路由表会有一个“默认的表项”(下一跳)-> 指向了一个更高层的路由器(认识的设备范围更广),这个路由器也可能查不到,也有下一跳 -> 更高层的路由器(认识的设备范围更更广)
上述讨论的过程是一个直观的认识流程,真实的转发过程更加复杂
2. 数据链路层
以太网帧格式
mac 地址和 IP 地址的区别
1. mac 地址使用 6 个字节表示;IP 地址使用 4 个字节表示
空间比 IP 地址大了 6w 多倍,mac 地址当前仍然可以给每个设备都分配一个唯一的 mac 地址值,一般一个网卡在出场的时候 mac 地址就被分配好了,写死了(不能改),因此 mac 地址可以作为设备的身份标识
2. mac 地址使用在数据链路层,用来实现两个设备之间的数据转发(微观)
IP 地址使用在网络层,立足于整个转发流程,进行路径规划(宏观)
理论上说,搞一套地址也能完成宏观和微观层次上的所有工作,IP 地址和 mac 地址留一组就可以了,但实际上两个都留下了,并且分配了不同的任务(不是技术问题,而是历史遗留问题)
ARP 协议
ARP 数据包 / ARP 协议,可以视为是让当前设备获取到周围设备 IP 地址和 mac 地址之间的映射关系
在 IP 协议路由转发的过程中,都是拿着 IP 地址来进行查路由表的,由此得到的是 “网络接口”(是一个抽象的概念),想要得到更具体的(要传输给哪个 mac 地址的设备),就涉及到当前 IP 地址对应到哪个 mac 地址的设备
当前设备接入网络的时候,就会往广播地址发送 ARP 报文,收到 ARP 请求的设备就会返回 ARP 响应,响应中就会告知自己的 IP 和 mac
RARP 则是反其道而行之,用来建立 mac 地址和 IP 地址之间的映射关系
MTU
将数组链路层数据帧的最大载荷长度 1500 字节称为 MTU,其和硬件直接相关,不同的硬件设备,对应到了不同的数据链路层协议,对应到了不同的 MTU
以太网的 MTU 就是很短的(1.5kb),IP /UDP 至少还是 64kb,因此此处的 MTU 限制,就会对上层协议产生直接影响
IP 协议之所以拆包组包,更多就是为了应对 MTU 的限制,当一个 IP 数据包达到 1500 以上的时候,就会自动拆包了
mac 地址在网络传输中变化的例子:
现假设要从西安到吉林省白城市安广镇感受八百里瀚海,会有以下规划:
3. 重要应用层协议 DNS(Domain Name System)
DNS 是一整套从域名映射到 IP 的系统
在网络中,虽然把 IP 写作点分十进制,但仍然对人类不友好,于是开始使用单词字符串来表示 IP 地址,称为域名
域名和 IP 地址存在对应关系,但是二者都不是一一对应关系
将域名转换为 IP 地址的一套系统就是“域名解析系统(DNS)”
早期的域名解析系统非常简单,仅仅通过一个文件来实现(hosts)
虽然仍然有效,但已经不使用了,因为网站太多了,域名很多,IP 地址很多,靠文件来维护不现实,不方便
为了解决上述问题,搭建了 DNS 服务器,把 hosts 文件放到 DNS 服务器里,当某个电脑需要进行域名解析时,直接访问 DNS 服务器