网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

4年前 (2022) 程序员胖胖胖虎阿
838 0 0

应用层、传输层、网络层、数据链路层、物理层

一、应用层协议

应用层 是程序猿最最经常打交道的一层

其他四层,都是操作系统、驱动、硬件,实现好了的,咱们不需要管 (除非你是系统工程师,驱动开发工程师…….)
在应用层这里,最最重要的事情,就是 “设计并实现一个应用层协议”

这是一个非常简单,同时也是在工作中经常要做的事情

举个栗子:

你们公司在开发一个项目,点外卖的软件
当前要开发一个功能,叫做获取用户的订单历史 (在数据库里,服务器来拿),这样的功能,就需要涉及到:

前端 (客户端) 和 后端 (服务器) 彼此之间的交互

  • 前端 和 后端 就是通过网络来进行交互的
  • 在这个交互的过程中,就需要约定好,前端发怎样的数据,后端会对应的数据

前端发的请求需要包含:(前端发的请求)

  • 用户的id

  • 查询的起始时间

  • 查询的结束时间

  • 显示的条数

  • 回来的响应:(后端返回的数据)

  • 查询是否成功:

  • 如果失败,失败的原因,

  • 结果数组:

  • 数组的每个元素就包含了一些属性商品名

  • 商品单价

  • 商品数量

  • 店铺名称

  • 总的金额

  • …

格式:

形如这样的工作,就是在设计一个应用层协议
上面的这部分工作,其实就是在规划 请求 和 响应 之间要传递的信息

光约定了传的信息,还不够,还得约定一个具体的格式

请求的格式形如:
1234\t2022-04-01\t2022-04-09\t10

响应的格式:
OK
“”
蛋炒饭\t10\t1\t沙县小吃\t10\n
炒面\t8\t1\t沙县小吃\t8\n

当前只是给出了一种可能的格式
此处这里数据的组织格式,也是可以随心所欲的约定的
相比之下,只要能够让 客户端 和 服务器 之间都按照─样的格式来交互就行了

设计一个应用层协议,主要就是包含两个工作:

  • 明确传输的信息
  • 明确数据的组织格式

正是因为这里的应用层协议,可以随心所欲的来指定,这就导致两极分化非常严重

上面这种设计就是一个不太好的设计

  1. 输出传输效率并不高运行效率低
  2. 可读性也不好,开发效率也低

正因为如此,大佬们发明了一些比较好的协议的模板,可以让我们直接往上套
当下比较流行的一些这种协议的模板 (数据的组织格式)

  1. xml 可读性好,但是运行效率不高

  2. json 可读性好,但是运行效率不高

  3. protobuffer 可读性不好,运行效率很高

  4. …


1、xml

xml 是属于一种比较老牌的数据格式了,现在虽然也在用,但是用的越来越少了
xml 的格式非常有特点:标签构成的

<标签名>内容</标签名>

:开始标签 要表示的值 结束标签

<request>
	<userld>1234</userld>
	<startTime>2022-04-01</startTime>
    <finishTime>2022-04-09</finishTime>
    <count>10</count>
</request>

标签名就是 key,标签值就是 value

通过这些标签,就更好的体现了这个数据的可读性,尤其是哪个部分是啥意思,非常一目了然

虽然 xml 提高了可读性,但是又引入了太多的辅助信息,这些标签名啥。一个服务器程序,最贵的硬件资源就是网络带宽!! (贼贵 !!!)
对于 xml 来说,因为要表示这些辅助信息,就导致传输相同数目的请求的时候,占用的网络带宽是更高的
如果带宽固定,相同时间能传输的请求个数就是更少的

因此,xml 现在很少作为应用层协议的设计模板了,现在使用 xml 主要是作为一些配置文件


2、json

json 当下最流行的一种,设计应用层协议的数据格式,咱们后面再工作中也会经常用到这个

{
	键 : 值,
    键 : 值,
	......
}

通过 {} 构成了键值对结构,一个 {} 中有很多个键值对,键值对之间使用逗号分割,键和值之间使用冒号分割。

要求键必须是字符串类型的;值允许很多种 (数字,字符串,布尔,数组,另一个 json…)

{
	userld: 1234,
	startTime: '2022-04-01',
    finishTime: '2022-04-O9",count: 10
}
  • json 中表示字符串:单引号或者双引号都可以 (类似于 SQL)
  • 最后一个键值对,后面可以有逗号,也可以没有 (标准要求是没有的,但是一般的 json 解析器,都不会在意这个细节)
  • json 要求 key 一定是字符串,因此 key 这里的引号可以省略,除非 key 中包含了一些特殊符号 (比如像空格,或者– …) 必须要加上引号

相比于 xml,json 同样能保证可读性,同时又没有 xml 那么繁琐 (占用的带宽要更少一点)


3、protobuffer

json 虽然传输效率比 xml 要高,但是仍然要多传递一些冗余信息,就是 key 的名字。
这一点在表示数组的时候,尤为明显,例如使用 json 表示响应格式:

{
	ok: true,
    reason: "",
    data: [
		{
			name: '蛋炒饭',
            price: 10,
			count: 1,
            totalPrice: 10
        },
		{
			name: "炒面',
            price: 8,
			count: 1,
            totalPrice: 8
        }
	]
}

上面是一个带有数组,带有嵌套的 json
当表示一个更加复杂的数据,比如数组的时候,此时这里的很多 key 就会重复出现 N 次, 也就占用了更多的额外带宽

  • protobuffer 应运而生,是一种二进制格式的数据
  • 在 protobuffer 的数据中,不再包含上面 key 的名字了,而是通过顺序以及一些特殊符号,来区分每个字段的含义
  • 同时再通过一个 IDL 文件 来描述这个数据格式 (每个部分是啥意思), IDL 只是起到一个辅助开发的效果,并不会真正的进行传输,传输的只是二进制的纯粹的数据

这是一个简化的表示版本:
13\3 蛋炒饭\210\21\210N3炒面\28\2\1\28

通过二进制的数据重新对这里的内容进行编排,甚至可能还会进行一些数据压缩
这样做传输效率会更高,但是也会让这个数据肉眼难以观察,调试起来就不方便了

json 的应用范围要比 protobuffer 更广,开发效率 > 运行效率

开发效率包含了 开发 和 调试
光论开发, protobuffer 有IDL (protobuffer 约定的一种文件格式,类似于 C 结构体的写法)

message Response {
	bool ok = 1,
	string reason = 2,
	repeated Data data = 3,
}

如果线上环境出问题
如果是用 json,出问题的请求和响应,一目了然。如果是用 protobuffer,二进制的数据,没法肉眼看,就得自己开发一个专门的程序来解析这个数据,分析这里的问题

设计应用层协议,是一件非常普遍的事情,也是一件并不复杂的事情

设计应用层协议,要做的工作:

  1. 明确**传输的信息 **(根据需求)
  2. 明确传输的格式 (参考现有模板, json,xml,protobuffer)

但是除此之外,业界也有一些现成的,已经被设计好,已经被广泛使用了的应用层协议
(也不是所有的时候,都需要从零设计,很多时候,可以直接基于现成的协议,稍加修改,稍加扩充,进行这种二次开发,类似于B站上的哪些鬼畜视频,二次创作)

其中最最知名的应用层协议,当属 HTTP


二、传输层重要协议

虽然传输层,是操作系统内核实现,程序猿不需要直接和传输层打交道。但是传输层对我们来说仍然意义重大!! 进行网络编程都要用到 socket。一旦你调用了 socket,代码就进入到传输层的范畴
如果一切顺利,就还好。一旦代码出现一些 bug,为了解决理解这些 bug,传输层的一些知识就是必要的了
传输层的协议,也是面试中特别爱考的 TCP 协议

详见此篇博客:【Java 网络编程】网络通信原理、TCP、UDP 回显服务

端口号:

整数,0 - 65535 之间的整数

知名端口号:把 0 - 1024 这些端口号,给划分出了一些具体的作用
很多网络服务是属于非常常用,非常广泛的服务。为了更好的管理,就给这些服务分配一些专门的端口号,并不是强制要求,而只是建议

80 http 服务器
443 https 服务器
22 ssh
23 ftp
…

如果你自己部署 http 服务器,可以把他绑定到 80,也可以绑定到其他端口上。像 java 中知名的 http 服务器 tomcat,使用的默认端口就不是80,而是 8080

传输层的协议有很多,其中最常见的就是 UDP 和 TCP
学习一个协议,很多时候就是在研究报文格式


三、UDP 协议

1、UDP 协议端格式

很多计算机网络的书上都会有,但是这种画法,其实是不对的 (容易给人误导),之所以这么画,只是为了印刷的时候排版

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

真正的情况:所谓的把应用层数据报分装成 UDP 数据报,本质上就是在应用层数据包的基础上,添加了 8 个字节的报头

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

**以 UDP 客户端为例:**代码中写的端口号,就会被打包到这样的 UDP 数据报中 (在报头中体现的)

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

此处报文长度是 2 个字节,范围 0 - 65535,0 - 64k (1k = 1024byte,64 * 1024 = 65536)
64k 大,还是小?够不够用?

  • 64k 大小在现代的互联网程序中,非常捉襟见肘了
    这是 UDP 使用中一个非常致命的缺陷,无法表示一个比较大的数据报,

如果确实需要传一个大的数据
可以在应用层,针对大的数据报,进行分包 (拆成多个部分),然后再通过多个 UDP 数据报,分别发送,这个时候,接收方再把收到的几个包重新拼接成完整的数据

  • 下策!太麻烦了
    拆包组包的代码,写起来非常复杂,要考虑到很多情况 (包丢了咋办,包的顺序错了咋办…)
  • 上策,就是改成 TCP,TCP 没有这样的长度限制

例如使用浏览器出现的广告:解决方案,就是把 UDP 直接改成 TCP

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制


2、校验和

是用来验证,网络传输的这个数据是否是正确的

  • 网络上传递的数据,本质是光信号和电信号
  • 但是,如果有一些外界干扰,磁场之类的… 就可能会导致原有的一些传递的信息发生了改变
    • 正常发一组连续的高频信号,因为遇到了一个强磁场,就可能导致其中的某些高频信号变成低频…
      (不考虑是否符合物理原理,只是打个比方)
    • 就可能导致 0 - 1 数据就错了,bit 翻转
  • 需要尽可能的识别出数据是不是错了,不能将错就错
    校验和 就能帮助我们发现数据中的错误

举个例子:

我去楼下买菜:黄瓜,鸡蛋,西红柿,芹菜

我拎着:黄瓜,鸡蛋,西红柿,韭菜

一共买四样

  • 校验和正确,不能保证数据 100% 就是对的,但是校验和不正确,一定认为数据是有问题的

  • 虽然如此,校验和仍然是广泛使用,成本非常低,效果非常好

  • 计算校验和的时候,也不一定单纯的就是使用 “个数”
    还可以使用数据内容参与运算,如果是基于数据内容得到的校验和,那么如果数据出错,被识别出来的概率是更高的

现在使用的一些用来生成校验和的算法 crc,md5,sha1 等等,这些操作都是基于内容来生成的校验

UDP 的校验和是针对 UDP 数据报检验了一次,以太网这里校验和是针对以太网数据帧校验了一次

述一个网络数据的时候,用了这几个词:
包,报,段,帧.……

  • 传输层的数据,通常叫做段 “segment”

  • 网络层的数据,通常叫做 包 / 报 “packet”

  • 数据链路层,通常叫做 帧 “frame”

很多时候咱们都不会去明确区分这几个概念

UDP 的特点:

UDP 传输的过程类似于寄信。

无连接,不可靠传输,面向数据报,全双工

无连接
知道对端的IP和端口号就直接进行传输,不需要建立连接;

不可靠
没有任何安全机制,发送端发送数据报以后,如果因为网络故障该段无法发到对方,UDP协议层也不会
给应用层返回任何错误信息

面向数据报
应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并;
用UDP传输100个字节的数据:

  • 如果发送端一次发送100个字节,那么接收端也必须一次接收100个字节;而不能循环接收10次,
    每次接收10个字节

全双工:

一条链路,双向通信

缓冲区:

UDP 只有接收缓冲区,没有发送缓冲区:

  • UDP 没有真正意义上的 发送缓冲区。发送的数据会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作;
  • UDP 具有接收缓冲区,但是这个接收缓冲区不能保证收到的 UDP 报的顺序和发送 UDP 报的顺序一致;如果缓冲区满了,再到达的UDP数据就会被丢弃;

大小受限

UDP协议首部中有一个16位的最大长度。也就是说一个UDP能传输的数据最大长度是64K(包含UDP首部)。

基于UDP的应用层协议

  • NFS:网络文件系统
  • TFTP:简单文件传输协议
  • DHCP:动态主机配置协议
  • BOOTP:启动协议(用于无盘设备启动)
  • DNS:域名解析协议

当然,也包括你自己写UDP程序时自定义的应用层协议


四、TCP 协议

1、TCP 协议段格式

TCP,即 Transmission Control Protocol,传输控制协议。人如其名,要对数据的传输进行一个详细的控制。
TCP 是一个非常非常重要的协议,不光在实际开发中广泛使用,同时也是面试中的高频问题

源/目的端口号:表示数据是从哪个进程来,到哪个进程去

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制


2、TCP中的一些核心机制

有连接,面向字节流,全双工:

  • 这三点在代码中都能体现出来

可靠传输:

  • 虽然代码上不能直接体现出来,但是这个却是 TCP 最最核心的机制
    引入 TCP 的关键原因,就是为了保证可靠传输!
    因此 TCP 中的很多机制,都是围绕这个可靠传输来展开

3、确认应答(安全机制)

3.1、举例:

TCP 对数据传输提供的管控机制,主要体现在两个方面:安全和效率。
这些机制和多线程的设计原则类似:保证数据传输安全的前提下,尽可能的提高传输效率。

  • 确认应答机制,就是保证可靠传输的核心机制
  • **可靠性:**发送方发出去数据之后,能够知道对方有没有收到
  • 关键就是接收方收到消息之后,给发送方,返回一个应答报文 (ACK, acknowledge),表示自己已经收到了

举个栗子:

我给女神发个短信,十几年前 07 左右的时候,手机短信是很容易发丢了的

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

当下这个确认应答,还有点小问题,如果我发了多个消息:

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

如果数据就是按照这样的方式来传输,倒还好。
我先发的吃麻辣烫,后发的做女票;我先收到的是 “好啊好啊”,后收到的是"滚"

网络上,数据接收的顺序,不一定和发送的顺序完全一致!!! 存在后发先至的情况!!

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

滚明明是后发的,但是反而先到了,

后发先至,对于网络来说,太常见不过的情况了,网络环境非常复杂,连续发的两个包,不一定就是走同一条路

如果大家参加过婚礼,接亲活动,也会遇到这种情况,等头车先到


3.2、编号

为了解决上述问题,办法也很简单:对消息进行编号

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

就是32位序号/32位确认号,确认序号:表示当前这个应答报文,是针对哪个消息进行的确认应答

TCP 的针对消息的序号,还有说法,并不是按 "消息条数” 来进行编号的,而是按照字节来编号

TCP 针对每个字节的数据都分别进行了编号。即为序列号

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

每一个 ACK 都带有对应的确认序列号,意思是告诉发送者,我已经收到了哪些数据;下一次你从哪里开始发。

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

A 给 B 发送了 1000 个字节,序号是 1 - 1000。发送的数据是 1 - 1000,意思是 TCP 报头中的序号是 1,报文长度是 1000,通过这个信息,来明确的范围。

主机 B 给 A 返回的应答报文 (ACK) 就会带有一个确认序号,叫做1001。小于 1001 的数据都已经被主机 B 收到了,
接下来主机 A 应该从 1001 这个序号开始往后进行传递

1 - 1000 这是同一个 TCP 数据报,这一个 TCP 数据报通过层层封装变成了一个以太网数据帧,进行传输,
如果传了多个数据报,分装成了多个以太网数据帧,多个数据帧之间才会出现后发先至


4、超时重传机制(安全机制)

4.1、举例:

相当于对确认应答进行了补充
确认应答是网络一切正常的时候,通过 ACK 通知发送方我收到了,如果出现了丢包的情况,超时重传机制就要起到效果了

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

当我发出去消息之后,就担心这个消息是不是发丢了,我就在等这个 ACK
如果确实消息发丢了,对方直接就没收到,我这里肯定也没法收到 ACK

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

另一个情况就是 ACK 丢了,虽然对方收到了消息,但是我收不到 ACK
对于发送方来说,我无法区分是哪种原因导致的没有收到 ACK,我就直接往坏了想,我就认为是对方压根没收到!!!

重新再发一次
这里的重发也不是立即就重发的,得等一会 (给点反应时间)
如果我等了 10 分钟 (超出了等待时间),还没有收到这个 ACK,就重发一次 (进行重传)!


4.2、去重

如果是 ACK 丢了,此时触发了超时重传,就会导致接收方收到了重复的消息!!
如果这里进行的操作不是请吃麻辣烫,而是转账,就会引起麻烦

TCP 内部就会有一个去重操作

  • 接收方收到的数据,会先放到操作系统内核的 “接收缓冲区” 中,接收缓冲区可以视为是一个内存空间,并且也可以视为是一个阻塞队列
  • 收到新的数据,TCP 就会根据序号,来检查看这个数据是不是在接收缓冲区中已经存在了,如果不存在,就放进去,如果存在,直接丢弃
  • 保证应用程序调用 socket API 拿到的这个数据一定是不重复的! 应用程序感知不到超时重传的过程的!

重发的这个数据是会重新封装
发送出去的数据,这是 TCP 负责发送的
调用一个 socket 中的 write 操作,本质上是把这个数据写到 TCP 的 “发送缓冲区” 中,由内核从发送缓冲区取数据,通过网卡传输 (也就是封装的过程)
当触发了超时重传的时候,内核再把刚才缓冲区的内容,重新再进行封装,重新传输
如果顺利收到了 ack ,就可以把这个数据从发送缓冲区中删掉
发送缓冲区也可以视为是一个阻塞队列,重传这个事情都是 TCP 干的事


4.3、重传时间

正常情况下,连续发丢了两次的概率是比较低的!!! 因此我就期望第二次发送是能够成功的,
如果网络不是有太大的问题,一般重传都是能成功的

超时重传,重传的数据,一定会成功嘛?肯定不是 100%

  • 如果只是因为网络抖动了一下,这个时候重传还是很容易成功的,如果是网络遭受了严重的伤害,可能没那么容易恢复,重传也成功不了了:网线断了 / 没有网费…,在这个情况下,重传不会一直进行

重传如果失败,可能还会再尝试,也不会无休止的重传
连续几次重传都不行,就认为这个网络可能是遇到了严重的情况,再怎么重传怕是也不行了,就只能放弃了 (自动的断开 TCP 的连接)
重传的这个时间间隔,也不是固定的,一般来说会逐渐变大 (重传的频率会逐渐降低)

—次传输失败的概率,本身就是比较小,连续两次传输都失败,概率就是小上加小。这个时候 TCP 基本就不太指望能够重传成功了,重传频率再高,大概率也是没啥用的,还不如省点力气
假设丢包概率为 10% (相当高的数字),连续两次丢包的概率就是 10% * 10% = > 1%
连续两次都丢包意味着当前丢包的概率已经远远高于 10% 了,接下来继续再发,能够顺利发过去的可能性也会是比较小的

如果超时的时间如何确定?

  • 最理想的情况下,找到一个最小的时间,保证 “确认应答一定能在这个时间内返回”。
  • 但是这个时间的长短,随着网络环境的不同,是有差异的。
  • 如果超时时间设的太长,会影响整体的重传效率;
  • 如果超时时间设的太短,有可能会频繁发送重复的包;

TCP为了保证无论在任何环境下都能比较高性能的通信,因此会动态计算这个最大超时时间

  • Linux中(BSD Unix和Windows也是如此),超时以500ms为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。
  • 如果重发一次之后,仍然得不到应答,等待 2*500ms 后再进行重传。 *
  • 如果仍然得不到应答,等待 4500ms 进行重传。依次类推,以指数形式递增。
  • 累计到一定的重传次数,TCP认为网络或者对端主机出现异常,强制关闭连接

5、连接管理机制(安全机制)

也是 TCP 保证可靠性的一个机制

[非常经典的面试题] TCP连接管理,是网络部分最高频的面试题,没有之一!!!

5.1、建立连接:三次握手

5.1.1、过程

在正常情况下,TCP 要经过三次握手建立连接,四次挥手断开连接

客户端和服务器之间,通过三次交互,完成了建立连接的过程,“握手” 是一个形象的比喻

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

客户端是主动发起连接请求的一方,客户端先发送一个 SYN 同步报文段,给服务器

SYN 同步报文段:

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

如果 SYN 这一位为 1,表示当前报文就是一个 “同步报文段”,主机 A 和主机 B 之间要建立连接

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

这个过程就像表白,双向奔赴的过程,双方都像对方表白,这个才算是正式确立关系

如果 ACK 这一位为 1,表示这个报文就是一个 “确认报文段”,(刚才说的确认应答报文,也是 ACK 为 1)

看起来是四次,但是中间的这两次,服务器发送的 ACK 和 SYN,是一定会合二为一的!!!
每次要传输的数据,都要经过一系列的封装和分用,才能完成传输
封装两次肯定不如封装一次来的更高效
例如我在某个淘宝店铺上,买了两件衣服,肯定是打一个包裹发给我更好的
让 ACK 和 SYN 合在一起也容易,让他们都是 1,所以是三次交互

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制


5.1.2、三次握手有何作用?和可靠性有什么关系?

  1. 三次握手,相当于是 “投石问路”,检查一下当前这个网络的情况是否满足可靠传输的基本条件
    如果你网络本身就效果非常差,强行进行 TCP 传输,也会涉及到大量丢包

例如相亲,先简单了解一下对方的情况,有没有房子,有没有车,收入有多少,有没有啥不良嗜好…

更具体的说,可以认为,三次握手其实也是在检测通信双方,发送能力和接收能力是否都正常
有的时候,可能我给同学们解决问题的时候,打字说不清,就需要QQ电话
打QQ电话的时候,我上来第一句话,喂喂喂,能听见嘛?

这个过程就是在验证通信双方的发送和接收能力是否都正常,验证麦克风和喇叭是不是都好使

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

  1. 让双方能够协商一些必要的信息

TCP 通信过程中,需要客户端和服务器之间,有一些共同的信息的
因此在三次握手的同时,也会相互之间交互一些必要的内容

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制


5.1.3、经典的面试题:

描述 TCP 三次握手的过程

为什么握手是三次?两次?四次?

针对这个问题,要画图
如果是线上面试(牛客),面试平台一般都是支持在线画图,如果是线下面试,你要记得自己带上纸币

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

TCP 三次握手的图,有很多版本,这是最简单的一个版本
还有在 SYN 和 ACK 上面标记上序号,和确认序号,还有标记上 TCP 状态转换的
还有标记上对应的 socket API 的

四次:

  • 行!但是没必要

  • 分开传输降低效率,不如合在一起好!

两次:

  • 不行!

  • 意味着缺少最后一次

    此时客户端这边,关于发送接收能力正常的情报是完整的,但是服务器这边是残缺的,服务器不知道自己的发送能力是否ok,也不知道客户端的接收能力是否ok

    此时此刻,服务器对于当下能否满足可靠传输,心里是没底的!!! 这第三次交互,就是为了给服务器吃一个定心丸


5.2、断开连接:四次挥手

5.2.1、过程

三次握于,就让客户端和服务器之间建立好了连接
其实建立好连接之后,操作系统内核中,就需要使用一定的数据结构来保存连接相关的信息!! 保存的信息其实最重要就是前面说的"五元组"
而且客户端,服务器都要保存五元组
源IP,源端口,目的IP,目的端口,TCP
既然是保存了信息就需要占用系统资源 (内存)

有朝一日,连接断开了,不复存在了)
此时之前保存了连接信息就没意义了,对应的空间也就可以释放了

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

双方各自向对方发送了 FIN (结束报文段)请求,并且各自给对方一个 ACK 确认报文,FIN 为 1 就表示这是一个结束报文段

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制


5.2.2、与三次握手的不同

  • 三次握手,一定是客户端主动发起的 (主动发起的一方才叫客户端)

    四次挥手,可能是客户端主动发起,也可能是服务器主动发起

  • 三次握手,中间两次能合并

    四次挥手,中间两次有时候合并不了 (有时候是能合并)

不能合并的原因,在于,B 发送 ACK 和 B 发送 FIN 的时机是不同的!!!

四次挥手中:

  • B 给 A 发的 ACK,是内核负责的;B 给 A 发的 FIN 是用户代码负责 (B的代码中调用了 socket.close() 方法,才会触发 FIN)
    收到 FIN,立即就由内核返回 ACK
    执行到用户代码中 close 才会触发,取决于用户代码咋写的
  • 如果这两操作之间的时间差,比较大,就不能合并了!
    如果时间差比较小,这是可能会合并的 (延时应答和捎带应答,后面再说)

三次握手中:

  • B 发送的 ACK 和 SYN 同一时机,就能够合并
  • 此处的 B 给A 发送的 ACK 和 SYN 都是操作系统内核负责进行的

5.2.3、服务端状态转化

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

关于状态转换的详细情况,不深入讨论,仍然要认识两个重要的状态

CLOSE_WAIT:

  • 四次挥手挥了两次之后出现的状态,这个状态就是在等待代码中调用 socket.close 方法,来进行后续的挥手过程。

  • 正常情况下,一个服务器上不应该存在大量的 CLOSE_WAIT,如果存在,说明大概率是代码 bug , close 没有被执行到

TIME_WAIT:

  • 谁主动发起 FIN,谁就进入 TIME_WAIT,起到的效果,就是给最后一次 ACK 提供重传机会

  • 表面上看起来,A 发送完 ACK 之后,就没有 A 的啥事了,
    按理说,A 就应该销毁连接,释放资源了,但是并没有直接释放,而是会进入 TIME_WAIT 状态等待一段时间,一段时间之后,再来释放连接

  • 等这一会,就是怕最后一个 ACK 丢包!!!
    如果最后一个 ACK 丢包了,就意味着,B 过一会就会重传 FIN

    示例:

如果最后一个 ACK 丢了 B,就收不到 ACK 了
B 是无法区分是 FIN 丢了,还是 ACK 丢了,于是 B 就假设是 FIN 丢了,于是就重传 FIN (超时重传)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Uvf8xmRM-1650383527520)(C:\Users\Chloe\AppData\Roaming\Typora\typora-user-images\image-20220414182739195.png)]

假设在这里 A 就释放了连接
当重传的 FIN 到达 A 之后,此时就无人能处理这个 FIN,也就无人能针对这个 FIN 进行应答了,
因此 A 的连接就不应该释放太早,要等待一段时间,确保 B 不会重传 FIN 了之后,再真正销毁连接

TIME_WAIT 应该持续多久呢?设定的时间是:2 * MSL
MSL 表示网络上任意两点之间,传输需要的最大时间,这个时间也是系统上可以配置的参数
一个典型的设置就是 60s (经验值)


6、滑动窗口(效率机制)

6.1、过程

刚才我们讨论了确认应答策略,对每一个发送的数据段,都要给一个ACK确认应答。收到ACK后再发送下一个数据段。这样做有一个比较大的缺点,就是性能较差。尤其是数据往返的时间较长的时候。

TCP 虽然可靠性是最高的机制,但是 TCP 也会尽可能的提高传输效率!!

既然这样一发一收的方式性能较低,那么我们一次发送多条数据,就可以大大的提高性能(其实是将多
个段的等待时间重叠在一起了)。

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

在这里可以看到,由于确认应答机制的存在,导致了当前每次执行一次发送操作,都需要等待上个 ACK 的到达,大量的时间都花在等 ACK 上了

滑动窗口,本质就是在 “批量的发送数据” 一次发一波数据,然后一起等一波 ACK

  • 窗口大小指的是无需等待确认应答而可以继续发送数据的最大值。上图的窗口大小就是4000个字节(四个段)。
  • 发送前四个段的时候,不需要等待任何ACK,直接发送;
  • 收到第一个ACK后,滑动窗口向后移动,继续发送第五个段的数据;依次类推;
  • 操作系统内核为了维护这个滑动窗口,需要开辟 发送缓冲区 来记录当前还有哪些数据没有
  • 应答;只有确认应答过的数据,才能从缓冲区删掉;
  • 窗口越大,则网络的吞吐率就越高;

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

TCP 是得保证可靠传输的,可靠传输的灵魂就是确认应答,如果没有这个 ACK,可靠传输就形同虚设。等,是不能不等!!

如果一次批量发送数据为 N,统一等待一波,此时这里 N 称为 “窗口大小”

“滑动” 的意思是,并不用把 N 组数据的 ACK 都等到了,才继续往下发送,而是收到一个 ACK,就继续往下发送—组

  • 当前是在等待 1001,2001,3001,4001 四组 ACK,不需要等到 4001 到了,才继续往下发
  • 只要 1001 到了,就可以往下多发一组 (4001 -5000),此时等待 ACK 的范围 2001,3001,4001,5001,
  • 如果是 2001 到了,就继续再往下发一组 (5001-6000),此时等待的 ACK 的范围 3001,4001,5001,6001

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制


6.2、丢包

当前这个窗口大小越大,可以认为就是传输速度就越快窗口大了,同一份时间内等待的 ACK 就更多,总的等待 ACK 的时间就少了

当前有一个核心问题:丢包
在滑动窗口的背景下,如果丢包,该如何重传呢?

丢包分成两种情况:

**情况一:**数据包已经抵达,ACK 被丢了

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

在这个图上,画的情况是 6 组 ACK,丢了 3 组

1、在发送 4001 之前,发现收到了一个 2001,此时没有收到 1001。2001 表示的意思就是:2001 之前的数据都已经确认收到了,1001 能否收到已经无足轻重了
ACK 确认序号的特定含义,就保证了后一条 ACK 就能涵盖前一条

因此,2001 意味着 1 - 2000 都收到了,既然如此,1 - 1000 更是已经收到了

2、当发送方收到 5001 的时候,意味着 1 - 5000 的数据都确认收到了。3001 和 4001 被丢包,也毫无影响,只要收到了 5001,就涵盖了 3001 和 4001 表达的信息

ACK 这里更像在闯,闯到了最后一关,说明前面的关都解锁了

如果是批量发送 1 - 4000 这些数据,当 ACK 收到了 4001 之后,意味着窗口一下就往后挪四个格子

情况二:数据包 就直接丢了

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

1、由于 1001 - 2000 这个数据丢了,所以 B 就再反复索要 1001 这个数据,即使 A 给 B 已经往后发了,这个时候仍然是在索要 1001,当索要若干次之后,A 就明白了,就触发了重传

2、当 A 重传了 1001 - 2000 之后,B 的接收缓冲区,就把缺口给补上了。
后续的 2001 - 7000 这些数据都是已经传输过了的,这些数据就不必再重传。接下来 B 就向 A 索要 7001 开始的数据

这里的重传只是需要把丢了的那一块数据给重传了即可
其他已经到了的数据就不必再重传了,整体的重传效率还是比较高的:快重传

这个快速重传就像看电视剧,以前大家看电视剧是使用电视看的,每天都是固定时间播放的,如果某天你有事了,其中某一集没看成,就只能继续往后看
过两天,发现另外一个电视台,也在放这个电视剧,就可以通过另外一个电视台,把缺了的那集给补完就可以了


7、流量控制(安全机制)

  • 是滑动窗口的延伸,目的是为了保证可靠性
  • 在滑动窗口中,窗口越大,传输速率就越高,但是不光要考虑发送方,还得考虑接收方,接收端处理数据的速度是有限的。
  • 如果发送端发的太快,导致接收端的缓冲区被打满,发送方发的贼快,接收方根本处理不过来了,这个时候如果发送端继续发送,接收方就会把新收到的包给丢了,造成丢包,继而引起丢包重传等等一系列连锁反应,发送方是不还得再重传
  • 因此 TCP 支持根据接收端的处理能力,来决定发送端的发送速度。这个机制就叫做 流量控制(Flow Control);

流量控制的关键,就是得能够衡量接收方的处理速度
此处,就直接使用接收方接收缓冲区的剩余空间大小,来衡量当前的处理能力

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

这样的数据传输过程,可以理解成 “生产者消费者模型”:

A:就是生产者
B:的应用程序就是消费者
B:的接收缓冲区,就是交易场所

接收缓冲区肯定有一个总大小

随着 A 发送数据,接收缓冲区里就会逐渐放入一些数据,剩余空间就会逐渐缩小

如果剩余空间比较大,就认为 B 的处理能力是比较强,就可以让 A 发的快点
如果剩余空间比较小,就认为 B 的处理能力是比较弱,就可以让 A 发的慢点

这个过程就像一个水池:

水池总大小,假设是 100 立方米,此时进水的速度,就取决于水池当前的水位高不高,

  • 水位高 (剩余空间小了),进水就慢点
    水位低 (剩余空间大了),进水就快点

就直接用剩余空间的大小来制约进水的速度,当然,剩余空间的大小,也是在侧面描述出水的速度
动态平衡

接收端如何把剩余空间多少 (窗口大小) 告诉发送端呢?

  • 通过 ACK 报文来告知,回忆我们的 TCP 首部中,有一个16 位窗口字段,就是存放了窗口大小信息;

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

通过这个 16 位窗口大小,来衡量当前接收方剩余空间的大小,

发送方收到这个数据之后,就会灵活的调整发送速度 (调整窗口大小)

那么问题来了,16位数字最大表示 65535,那么TC P窗口最大就是 65535 字节么?
虽然这里是 16 位,实际上这里的窗口大小不止是 64k,还可以更大
实际上,TCP 首部 40 字节选项中还包含了一个 窗口扩大因子 M,实际窗口大小是 窗口字段的值左移 M位;

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

**当窗口大小为 0,是否意味着 A 就不再发送数据了?**A 确实是不发送了,但是又不是完全不发送,水池满了,就不应该继续注水了
但是放水是不仍然在进行 (满并不是一直满,满一会就不满)

虽然 B 反馈的窗口大小是 0,但是 A 也不能完全不发数据
需要定期的发送一个探测报文,探测报文不传输实际的数据,只是为了触发 ACK,只是为了知道当前的窗口大小是多少


8、拥塞控制(安全机制)

  • 也是滑动窗口的延伸,也是限制滑动窗口发送的速率

    拥塞控制衡量的是,发送方到接收方,这整个链路之间,拥堵情况 (处理能力)

  • 虽然 TCP 有了滑动窗口这个大杀器,能够高效可靠的发送大量的数据。但是如果在刚开始阶段就发送大量的数据,仍然可能引发问题

  • 因为网络上有很多的计算机,可能当前的网络状态就已经比较拥堵。在不清楚当前网络状态下,贸然发送大量的数据,是很有可能引起雪上加霜的

  • TCP 引入 慢启动机制,先发少量的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

A 能够发多快,不光取决于 B 的处理能力,也取决于中间链路的处理能力

A 和 B 之间的中间节点,有多少个?不知道,很多,就很难对这些设备逐一衡量

拥塞控制的处理方案,就是通过 “实验" 的方式,逐渐调整发送速度,找到一个比较合适的值 (范围)

A 开始的时候以一个比较小的窗口来发送数据,如果数据很流畅的就到达了,逐渐加大窗口大小,如果加大到一定程度之后,出现了丢包 (丢包就意味着通信链路出现拥堵了),这个时候再减小窗口

通过反复的增大 / 减小过程,逐渐就摸到了一个合适的范围,拥塞窗口就在这个范围中不断变化,达到 “动态平衡”

具体这个拥塞窗口是如何变化的呢?

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

此处引入一个概念程为拥塞窗口
发送开始的时候,定义拥塞窗口大小为 1;
每次收到一个ACK应答,拥塞窗口加 1;
每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口大小做比较,取较小的值作为
实际发送的窗口;

像上面这样的拥塞窗口增长速度,是指数级别的。“慢启动” 只是指初使时慢,但是增长速度非常快。

为了不增长的那么快,因此不能使拥塞窗口单纯的加倍。
此处引入一个叫做慢启动的阈值
当拥塞窗口超过这个阈值的时候,不再按照指数方式增长,而是按照线性方式增长
当 TCP 开始启动的时候,慢启动阈值等于窗口最大值;
在每次超时重发的时候,慢启动阈值会变成原来的一半,同时拥塞窗口置回1;

少量的丢包,我们仅仅是触发超时重传;大量的丢包,我们就认为网络拥塞;
当 TCP 通信开始后,网络吞吐量会逐渐上升;随着网络发生拥堵,吞吐量会立刻下降;

拥塞控制,归根结底是TCP协议想尽可能快的把数据传输给对方,但是又要避免给网络造成太大压力的折中方案。
TCP拥塞控制这样的过程,就好像 热恋的感觉


9、延时应答(效率机制)

  • 相当于流量控制的延伸。
  • 流量控制是踩了下刹车,使发送方,发的不要太快
    延时应答,就想在这个基础上,能够尽量的再让窗口更大一些

如果接收数据的主机立刻返回 ACK 应答,这时候返回的窗口可能比较小。

  • 假设接收端缓冲区为 1M。一次收到了 500K 的数据;如果立刻应答,返回的窗口就是 500K;
  • 但实际上可能处理端处理的速度很快,10ms 之内就把 500K 数据从缓冲区消费掉了;
  • 在这种情况下,接收端处理还远没有达到自己的极限,即使窗口再放大一些,也能处理过来;
  • 如果接收端稍微等一会再应答,比如等待 200ms 再应答,那么这个时候返回的窗口大小就是 1M;

一定要记得,窗口越大,网络吞吐量就越大,传输效率就越高。我们的目标是在保证网络不拥塞的情况下尽量提高传输效率;

那么所有的包都可以延迟应答么?肯定也不是;

  • 数量限制:每隔 N 个包就应答一次;
  • 时间限制:超过最大延迟时间就应答一次;

具体的数量和超时时间,依操作系统不同也有差异;一般 N 取 2,超时时间取 200ms

举个栗子:

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

注水的同时也在出水

每次注入一波水,就会询问当前水池里剩余空间有多少

采取的策略就是不立即回答,而是稍微晚一会回答,迟一点回答,意味着在这个延时间里,就会出更多的水
如果立即回答,可能回答一个剩余 20 吨,如果延时一会回答,就可以说,剩余 30 吨 (延时这个时间里出了 10 吨水)

这个操作就是在有限的情况下,又尽可能的提高了一点传输速度


10、捎带应答(效率机制)

  • 延时应答的延伸
  • 在延迟应答的基础上,我们发现,很多情况下,客户端服务器在应用层也是 “一发一收” 的。意味着客户端给服务器说了 “How are you”,服务器也会给客户端回一个 “Fine, thank you”;
    那么这个时候 ACK 就可以搭顺风车,和服务器回应的 “Fine,thank you” 一起回给客户端

客户端和服务器之间的通信,有以下几种模型:
1、一问一答:客户端发一个请求,服务器返回一个对应的响应
2、多问一答:上传文件
3、一问多答:下载文件
4、多问多答:直播,串流…

用浏览器上网,打开网页,主要就是这种模型一问一答

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

因为延时应答的存在,导致 ACK 不一定是立即返回的!!
如果当前的延时应答,导致 ACK 的返回时机 和 应用代码中返回的响应时机 重合了!!! 就可以把这个 ACK 和响应数据,合二为一


11、其他特性:面向字节流

11.1、其他特性

其他特性:面向字节流
其他特性:缓冲区
其他特性:大小限制

创建一个TCP的socket,同时在内核中创建一个 发送缓冲区 和一个 接收缓冲区

  • 调用write时,数据会先写入发送缓冲区中;
  • 如果发送的字节数太长,会被拆分成多个TCP的数据包发出;
  • 如果发送的字节数太短,就会先在缓冲区里等待,等到缓冲区长度差不多了,或者其他合适的时机发送出去;
  • 接收数据的时候,数据也是从网卡驱动程序到达内核的接收缓冲区;
  • 然后应用程序可以调用read从接收缓冲区拿数据;
  • 另一方面,TCP的一个连接,既有发送缓冲区,也有接收缓冲区,那么对于这一个连接,既可以读数据,也可以写数据。这个概念叫做 全双工

由于缓冲区的存在,TCP程序的读和写不需要一一匹配,例如:

  • 写100个字节数据时,可以调用一次write写100个字节,也可以调用100次write,每次写一个字节;
  • 读100个字节数据时,也完全不需要考虑写的时候是怎么写的,既可以一次read 100个字节,也可以一次read一个字节,重复100次;

11.2、粘包问题

(不仅仅 TCР 存在粘包(nian / zhan),其他的面向字节流的机制,也存在,比如读文件)
TCP 粘包指的是,粘的是应用层数据报,在 TCР 接收缓冲区中,若干个应用层数据包混在一起了,分不出来谁是谁了

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

解决方案: 关键就是要在应用层协议这里,加入包之间的边界 (粘包问题,说是在 TCP 这里讲的实际上这是个应用层的问题)

例如,约定每个包以 ; 结尾
如果你是基于一些库 / 框架来完成网络通信,一般来说粘包问题已经被库 / 框架处理了,如果你是需要自己实现一些库 / 框架,直接使用了 TCP,就需要考虑到粘包了

  • 对于定长的包,保证每次都按固定大小读取即可;例如上面的Request结构,是固定大小的,那么就从缓冲区从头开始按sizeof(Request)依次读取即可;
  • 对于变长的包,可以在包头的位置,约定一个包总长度的字段,从而就知道了包的结束位置;
  • 对于变长的包,还可以在包和包之间使用明确的分隔符(应用层协议,是程序猿自己来定的,只要保证分隔符不和正文冲突即可);

思考: 对于UDP协议来说,是否也存在 “粘包问题” 呢?

  • 对于UDP,如果还没有上层交付数据,UDP的报文长度仍然在。同时,UDP是一个一个把数据交付给应用层。就有很明确的数据边界。
  • 站在应用层的站在应用层的角度,使用UDP的时候,要么收到完整的UDP报文,要么不收。不会出现"半个"的情况。

五、TCP 异常情况

1、进程终止

  • 在进程毫无防备的情况下,偷袭他,突然结束进程,这个时候该进程的 TCP 连接是咋样的??
  • TCP 连接,是通过 socket 来建立的,socket 本质上是进程打开的一个文件,文件其实就存在于进程的 PCB 里面,有个文件描述符表,每次打开一个文件 (包括 socket),都在文件描述符表里,增加一项
    每次关闭一个文件,都在文件描述符表里,进行删除一项
  • 如果直接杀死进程,PCB 也就没了,里面的文件描述符表也就没了,此处的文件相当于 '自动关闭’ 了,这个过程其实和手动调 socket.close() 一样,都会触发 4 次挥手,

2、机器关机

按照操作系统约定的正常流程关机
正常流程的关机,会让操作系统,杀死所有进程,然后再关机,还是一样


3、机器掉电 / 网线断开

台式机,直接拔电源,偷袭成功!!!

操作系统不会有任何反应时间,更不会有任何的处理措施

接收端认为连接还在,一旦接收端有写入操作,接收端发现连接已经不在了,就会进行 reset。即使没有写入操作,TCP自己也内置了一个保活定时器,会定期询问对方是否还在。如果对方不在,也会把连接释放

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

如果 B 断电
意味着 A 发送的数据不再有 ACK 了,A 进入超时重传逻辑
重传几次之后,A 认为这个连接已经出现严重故障了,尝试重新建立连接,重连失败之后就会放弃连接 (A 主动释放曾经和 B相关的连接信息)

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

如果 A 断电
B 就不知道当前是 A 挂了,还是 A 休息会再继续
B 就会时不时的给 A 发送一个小的报文 (探测报文,心跳包,不带有实际的数据,只是为了触发 ACK)
通过探测报文,发现 A 不再返回 ACK 了,因此 B 就认为 A 出现了问题

另外,应用层的某些协议,也有一些这样的检测机制。例如HTTP长连接中,也会定期检测对方的状态。例如QQ,在QQ断线之后,也会定期尝试重新连接


总结:

可靠性:

  • 校验和
    序列号(按序到达)
    确认应答
    超时重发
    连接管理
    流量控制
    拥塞控制

提高性能:

  • 滑动窗口
    快速重传
    延迟应答
    捎带应答

其他:

  • 定时器(超时重传定时器,保活定时器,TIME_WAIT定时器等)

基于TCP应用层协议

  • HTTP
    HTTPS
    SSH

  • Telnet
    FTP
    SMTP

当然,也包括你自己写TCP程序时自定义的应用层协议;

为什么TCP这么复杂?因为要保证可靠性,同时又尽可能的提高性能 ,可靠性的基础上,保证效率

  • TCP vs UDP 对比:
    • 什么时候使用TCP?对可靠性有一定要求,应用于文件传输,重要状态更新等场景; (日常开发中的大多数情况,都是基于 TCP)
    • 什么时候使用UDP?对可靠性要求不高,对高速传输和实时性要求较高的通信领域,例如,早期的QQ,视频传输等。另外
      UDP可以用于广播; (典型的例子,机房内部的主机之间通信,分布式系统中)
    • 归根结底,TCP和UDP都是程序员的工具,什么时机用,具体怎么用,还是要根据具体的需求场景去判定
  • 传输层的协议,只有 TCP 和 UDP 嘛?
    • 像当下常见的,LOL,Dota2,吃鸡,王者荣耀…这些对抗性很高的游戏,底层是使用 TCP 还是 UDP

**经典面试题:**基于 UDP 如何实现可靠传输??

  1. UDP 本身是无连接,不可靠,面向数据报的协议,如果要基于传输层 UDP 协议,来实现一个可靠传输,应该如何设计?

  2. UDP 大小是受限的,如果要基于传输层 UDP 协议,传输超过 64K 的数据,应该如何设计?

以上两个问题答案类似,都可以参考 TCP 的可靠性机制在应用层实现类似的逻辑:[其实在考 TCP]

抄作业!!! 本质上就是,在应用层基于 UDP 复刻 TCP 的机制

例如:

  • 引入序列号,保证数据顺序;
  • 引入确认应答,确保对端收到了数据;
  • 引入超时重传,如果隔一段时间没有应答,就重发数据;
    ……

六、网络层 —— IP 协议

1、IP 协议段格式

在复杂的网络环境中确定一个合适的路径。

完成两方面工作:

  1. 地址管理

  2. 路由选择

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

3)TOS说是8位,其实只有4位是有效的一

4 位版本号(version):

指定 IP 协议的版本,当前只有两个取值:4 和 6,0100,0110。对于 IPv4 来说,就是 4。

4 位头部长度(header length):

IP 的报头和 TCP 类似,都是可变的,带有选项,4 位的取值范围 0 - 15,这里的单位也是 4 字节,如果取值是 1111 => 15,实际表示的首部长度就是 60 字节。IP 头部的长度是多少个32bit,也就是 length * 4 的字节数。4bit表示最大的数字是 15,因此 IP 头部最大长度是 60 字节。

8 位服务类型(Type Of Service):

  • TOS 说是 8 位,其实只有 4 位是有效的。3 位优先权字段(已经弃用),4 位 TOS 字段,和 1 位保留字段(必须置为 0)。4 位 TOS 分别表示:最小延时,最大吞吐量,最高可靠性,最小成本 (同一时刻,只能取一种状态),这里的 TOS 相当于是切换形态 (类似于变身效果),

  • IP 协议能够规划处两点之间一条比较合适的路径,翻译翻译,啥叫合适??

  • 这四者相互冲突,只能选择一个。对于 ssh / telnet 这样的应用程序,最小延时比较重要;对于 ftp 这样的程序,最大吞吐量比较重要。

16 位总长度(total length):

  • IP数据报整体占多少个字节。
  • UDP好像也有类似的情况,16位 => 最大长度 64k
    因此,单个 IP 数据报最大长度确实不能超过 64k
  • 如果要构造一个更长的数据报 (比如搭载的载荷部分已经超过 64k了,咋办?)
    IР 协议自身实现了分包和组包这样的操作

这三个字段就是用来进行分包和组包的:

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

第二个没有 TCP 报头,对于 IP 数据包来说,根本不关心载荷里是啥,只是单纯的对数据进行了切分了,也不知道这里有没有 TCP 报头

如何区分这多个 IP 包,是从同一个数据拆分来的呢??

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

16 位标识(id):

唯一的标识主机发送的报文。如果 IP 报文在数据链路层被分片了,那么每一个片里面的这个 id 都是相同的。例如快递单号,即使是拆成多个包裹,多个包裹的快递单号也是一样的,多个被拆出的IР数据报,的16位标识的值是相同的

3 位标志字段:

  • 3 位中只有一位是好使的,0 表示还有后续,1表示这是最后一个包了 (结束标记)

  • 第一位保留(保留的意思是现在不用,但是还没想好说不定以后要用到)。

  • 第二位置为 1 表示禁止分片,这时候如果报文长度超过MTU,IP模块就会丢弃报文。

  • 第三位表示 “更多分片”,如果分片了的话,最后一个分片置为1,其他是0。类似于一个结束标记。

13 位分片偏移(framegament offset):

  • 通过这个 13 位片偏移,来描述这多个包谁先谁后
  • 是分片相对于原始 IP 报文开始处的偏移。其实就是在表示当前分片在原报文中处在哪个位置。实际偏移的字节数是这个值 * 8 得到的。因此,除了最后一个报文之外,其他报文的长度必须是8的整数倍(否则报文就不连续了)。

8 位生存时间(Time To Live,TTL):

  • 数据报到达目的地的最大报文跳,表示一个 IP 数据报,在网络上还能存在多久,这里的单位不是 s 或者 ms,而是转发次数
    IP 数据报被发送的时候,会有一个初始的 TTL (比如常见的取值,128 或者 64),IP 数据报每次经过了一个路由器,TTL 就会 –1,如果 TTL 减到 0 了,此时收到这个包的路由器就会把这个包给丢弃,

  • 主要就是有些包里面的 IP 地址可能是永远也到不了的,像这样的包,不可能在网络上无休止的转发(占用硬件资源太多了),一直减到0还没到达,那么就丢弃了。这个字段主要是用来防止出现路由循环。

  • 正常的 IP 数据报都会在既定的 TTL 内来到达

8 位协议:

表示上层协议(传输层) 的类型,TCP 或者是 UDP 都有不同的取值

16 位头部校验和:

也是使用 CRC 来校验数据是否正确,头部是否损坏。

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

32 位源地址和 32 位目标地址:

  • 表示发送端和接收端。源 IP 表示发件人地址,目的 IP 表示收件人地址
  • 对于 IPv4 来说,一个 IP 地址本质上是 32 位的整数,通常会使用 “点分十进制” 这样的方式来表示这个 IP 地址,
    三个点,把 32 位整数分成 4 个部分,每个部分 1 个字节,每个部分的取值就是 0-255,
    如:192.168.0.5
    给人看的 IP 通常就是点分十进制表示的,给机器存储的 IP,在底层仍然是按照 4 个字节整数来表示

选项字段(不定长,最多40字节):

略。


2、IP 地址

IP地址(Internet Protocol Address)是指互联网协议地址,又译为网际协议地址

差异:

IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异

IP地址是一个32位的二进制数,通常被分割为4个“8位二进制数”(也就是4个字节),如:
01100100.00000100.00000101.00000110
IP 地址是一个点分十进制构成的数据,即 a.b.c.d 的形式(a,b,c,d都是0~255之间的十进制整数)。如:100.4.5.6,

组成:

咱们把 IP 地址分成了两个部分:网络号 + 主机号

  • 网络号:描述当前的网段信息(局域网的标识) 证相互连接的两个网段具有不同的标识;

  • 主机号:区分了局域网内部的主机 同一网段内,主机之间具有相同的网络号,但是必须有不同的主机号;

  • 192.168.0.5
    网络号 主机号

要求,同一个局域网里,主机之间的网络号是相同的,主机号不能相同。两个相邻的局域网 (同一个路由器连接的),网络号也是不同的

通过合理设置网络号和主机号,就可以保证在相互连接的网络中,每台主机的IP地址都是唯一的。
那么,如何划分网络号和主机号呢?


3、IP 地址分类

过去曾经提出一种划分网络号和主机号的方案,把所有IP 地址分为五类,
网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

分 类 范围 适用网络 网络数量 主机最大连接数
A 类 0.0.0.0 ~ 127.255.255.255 大型网络 126 16777214(

2

24

2^{24}

224-2)

B 类 128.0.0.0 ~ 191.255.255.255 中等规模 网络 约16000 个 65534(

2

16

2^{16}

216-2)

C 类 192.0.0.0 ~ 223.255.255.255 小型网络 - 254(

2

8

2^8

28-2)

D 类 224.0.0.0 ~ 239.255.255.255

备注:主机最大连接数减去2,是扣除主机号为全0和全1的特殊IP地址

—些特殊的 IP 地址:

  • 如果 IP 的主机号为全 0,该 IP 就表示网络号 (局域网里的一个正常的设备,主机号不能设为 0)
  • 如果 IP 的主机号为全 1 (255),该 IP 就表示 “广播地址”,往这个广播地址上发的消息,整个局域网中都能收到
  • IP 地址是 127 开头的,该 IP 都表示 “环回IP”,表示主机自己
    127.0.0.1 (环回IP中的典型代表)
  • IP地址是 10 开头,192.168 开头,172.16 - 172.31 开头,表示该 IP 地址是一个局域网内部的 IP (内网 IP),
  • 除此之外,剩下的 IP 称为 外网 IP (直接在广域网上使用的 IP)
    要求外网 IP 一定是唯一的,每个外网 IP 都会对应到唯一的一个设备,
  • 内网 IP 只是在当前局域网中是唯一的,不同的局域网里,可以有相同的内网 IP 的设备

在上述的分类中,存在IP地址浪费的问题:
1)单位一般会申请B类网络(C类连接主机数量有限),但实际网络架设时,连接的主机数量又常远
小于65534(B类连接主机数),造成IP地址浪费;同理,A类网络的IP地址也会造成大量的浪费。
(2)当一个单位申请了一个网络号。他想将该网络能表示的IP地址再分给它下属的几个小单位时,如
果在申请新的网络就会造成浪费。
为了解决以上问题,引入子网掩码来进行子网划分:


4、子网掩码

到底前多少个 bit 位是网络号?怎么规定的呢?固定 3 个字节嘛?? 其实是不固定的 !!!
引入了一个 “子网掩码" 这样的概念,来表示多少个 bit 位是网络号

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

格式:

  • 也是一个 32位,点分十进制 表示的整数
  • 子网掩码的左侧都是 1,右侧都是 0 (不会 1 0 混着排列)
  • 左边的这些 1 就表示哪些位是网络号,剩下 0 就是表示哪些位是主机号

作用
(1)划分A,B,C三类 IP 地址子网:

  • 如一个B类IP地址:191.100.0.0,按A ~ E类分类来说,网络号二进制数为16位网络号+16位主机号。
  • 假设使用子网掩码 255.255.128.0(即17) 来划分子网,意味着划分子网后,高17位都是网络位/网络号,也就是将原来16位主机号,划分为1位子网号+15位主机号。
  • 此时,IP地址组成为:网络号+子网号+主机号,网络号和子网号统一为网络标识(划分子网后的网络号/网段)

(2)网络通信时,子网掩码结合IP地址,可以计算获得网络号(划分子网后的网络号)及主机号(划分子网后的主机号)。一般用于判断目的IP与本IP是否为同一个网段。

对于网络通信来说,发送数据报时,目的主机与发送端主机是否在同一个网段,流程是不一样的

计算方式

  • 将 IP 地址和子网掩码进行“按位与”操作(二进制相同位,与操作,两个都是1结果为1,否则为0),得到的结果就是网络号。
  • 将子网掩码二进制按位取反,再与 IP 地址位与计算,得到的就是主机号。

示例:

十进制 二进制
IP地址 180.210.242.131 10110100.11010010.11110010.10000011
子网掩码 255.255.248.0 11111111.11111111.11111000.00000000
网络号 180.210.240.0 10110100.11010010.11110000.00000000
主机号 0.0.2.131 00000000.00000000.00000010.10000011

5、解决 IPv4 不够用:

255 => 1111 1111 1111 1111 1111 1111 0000 0000
IP 地址中的前 24 个 bit 位就是网络号,后 8 个 bit 位就是主机号

一般家用的场景中,一个局域网设备很少 (不会超过 255),常见的子网掩码就是2 55.255.255.0
如果一个局域网设备多了,子网掩码就会出现一些其他值

需要根据实际需要来确定网段如何划分,(每个设备的 IP 都是可配置的,包括子网掩码啥的,都是可以修改的)

负责配置网络的人,有一个专门的岗位:网管!!! 网络管理员,网管 != 网管儿
负责一些大型网络的维护的

内网IР是可以重复的,本来咱们预期 IP 地址应该就表示一个网络上的唯一位置,结果为什么同一个 IP 能表示不同设备了呢??

当前 IPv4 协议,使用的 IP 地址是 32 位的整数,32 位能表示的数据范围
42 亿 9 千万
如果给每个设备都分配一个唯一的 IP 地址,意味着世界上的设备就不能超过 42 亿 9 千万,随着网络的发展,现在世界上的设备越来越多,已经超过了 42 亿 9 千万,让每个设备都有唯一的 IP 地址不现实了 (现在尤其是移动互联网的兴起),如何解决这个问题?

方法一:动态分配 IP 地址:

让每个设备连上网的时候,才有IP,不联网的时候就没 IP (这个 IP 就可以给别人用)
但是这个方案不能从根本上解决问题 (设备没有减少,IP 地址也没有增加…) 治标不治本

方法二:NAT 机制

  • 让多个设备共用同一个 IP (外网 IP) [当前网络环境]
  • 把网络分成了内网(局域网) 和 外网(广域网),要求外网 IP 必须表示唯一的设备,同时内网中的若干个设备,可以共用同一个外网 IP !!!
  • 这个时候每个外网 IP 都可能表示着几千个,甚至上万个设备,这个时候 IP 地址的压力就缓解了很多了

运营商的路由器这里就会修改 IP 数据报,从内网发出去的源 IP 改成外网 IP 带有这样功能的路由器设备,也称为 NAT 设备,

NAT 机制,把 IP 分成了内网和外网,也就隐含了一个重要的结论:
对于一个外网 IP,可以在互联网的任意位置都能访问到
对于一个内网 IP,只能在当前局域网内部访问,局域网 1 的设备,不能使用 内网 IP (内网 IP 可以重复出现,只有在当前局域网内才是唯一的) 访问 局域网 2 的设备

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

例如:192.168.0.5,
这个 IP 只有在我自己家里的局域网中才能访问,别人想跨越局域网来访问我的这个 IP 这个是做不到的!!!
如果咱们之间要想通信咋办? 就需要有一个带有外网 IP 的机器,在这里其实就是 cctalk 服务器
cctalk 服务器是有 外网 IP,咱们都能访问到 cctalk,我这边的机器,访问了 cctalk,把我的电脑的画面推送到 cctalk 服务器上,有人也问了 cctalk,从 cctalk 上拿我的直播画面
如果没有 NAT (如果所有的 IP 都是唯一的),就可以做到,不通过 cctalk,我直接在我自己的电脑上架设一个直播服务器,大家直接访问我的 IP 就行了

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

NAT 也是存在极限的,端口号的个数 65535,如果一个局域网里的连接超过了 65535,这个时候,NAT 就不一定能好使了,端口号就不够用了,NAT 只是续命了一波,但是不是从根本上解决问题

方法三:lPv6

IPv6 在报头中使用了一个更长的字段,来表示 IP 地址,16个字节,128 位,2 * 128
看起来好像是 16 个字节比 4 个字节,大了 4 倍,其实不是,而是大了很多很多
4 个字节,32 位:2 ^ 32 * 2 ^ 32 * 2 ^ 32 * 2 ^ 32
号称 IPv6 可以给地球上的每个沙子都分配一个 IP 地址,lPv6 是真正从根本上解决了 IP 地址不够用的问题!!!

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

每个数字都是一个十六进制的数字(4bit),每个冒号分割了 2 个字节

既然 IPv6 非常好,为什么现在还是在用 IPv4 + NAT 呢?

这里最大的问题在于,IPv6 和 IPv4 是不兼容的!!!
对于一个设备来说,支持 IPv4 和 IPv6 需要两个截然不同的机制,现有的大量的网络设备(路由器…)很可能都是只支持 IPv4,不支持 IPv6,因此,要想升级到 IPv6,就得更换设备,换设备就得加钱!!!

中美贸易战,美国针对中国各个方面都进行了封锁,IPv4 的外网 IP 的分配权限就是在美手里的,一旦要是再 IP 分配上动手脚,就会对中国互联网发展产生很大的影响

IP 地址网段划分,是通过子网掩码的方式划分的…
在历史上(有子网掩码之前)
是简单粗暴的通过 “分类” 的方式来划分的,把 IP 地址分成了 A,B,C,D,E
这五类,每一类,分别都有几位是网络号,几位是主机号…(淹没在历史长河中了)


3、路由选择

所谓路由,即在复杂的网络结构中,找出一条通往终点的路线;
网络通信(网络数据传输),路由器中的路由功能,就类似于规划路线,往哪个方向行进能更快到达目的地。
两个设备之间,要找出一条通道,能够完成传输的过程,要想找出通道,前提是,得先认识路

例如我要去某个地方,只知道大致的方向,于是先乘坐 128 路公交车,到站后问路,问了一个人,他也不知道具体路线,但知道可以 33 路到终点站,接下来我就继续问了一个人,直到目的地在哪里,于是就找到了

IP 协议的路由选择也是类似的,IP 数据报中的目的地址,就表示了这个包要发到哪里去
这个目的地址,如果当前路由器直接认识,就直接告诉你路了,如果当前路由器不认识,,会告诉你一个大概的方向,让你走到下一个路由器的时候再来问问
依次往后走,其实也是在离目标越来越近
这个时候就总会遇到一个认识这个地址的路由器,于是就可以具体的转发过去了
有的时候,不光遇到了一个认识这个地址的路由器,并且它还认识多个路,就可以选一个更合适的路了

什么叫路由器 “认识” 这个IP地址:

  • 在路由器内部维护了一个数据结构,路由表

  • 路由表里面就记录了一些网段信息(网络号),(目的 IP 就再这些网络号中匹配),以及每个网络号对应的网络接口 (网辂接口其实就对应到路由器里面具体的端口)

路由表内部的结构不复杂,复杂的是路由表是咋来的,(有一系列专门的路由表生成算法,自动生成一波,还可以手动配置)

具体实现细节复杂,思想上还比较清晰:
某个路由器上线(接入网络之后),就会和相邻的设备进行通信,“认识一下”,在这个认识的过程中,路由器就来构造这个路由表,这个认识不一定就是紧挨着的,路由器是可能会认识到更多的 “朋友”

路由表中的一个默认表项起到的效果,当 IP 地址在路由表的所有表项中都匹配不上的时候,此时就会走这个下一跳


七、数据链路层

1、以太网

“以太网” 不是一种具体的网络,而是一种技术标准;既包含了数据链路层的内容,也包含了一些物理层的内容。例如:规定了网络拓扑结构,访问控制方式,传输速率等;

例如以太网中的网线必须使用双绞线;传输速率有10M,100M,1000M等;
以太网是当前应用最广泛的局域网技术;和以太网并列的还有令牌环网,无线LAN等;

数据链路层主要的协议,叫做 “以太网”。像平时咱们插的网线,就叫做 “以太网线”

以太本来是物理学上的概念
之前大家认为光也是一种波,必须要依靠介质才能传播(类似于声波)真空中,光也能传播
于是就脑补出了一个介质:以太
迈克尔逊-莫雷实验,证明了光速在各个方向上,都是一致,推翻了以太 => 狭义相对论

以太网这个协议不仅仅规定了数据链路层的内容,也规定了物理层的内容


2、以太网帧格式

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

通过 6个 字节 来表示源地址和目的地址,这个就要比 IPv4 更长,长了 6w 多倍,此处的源地址 / 目的地址,使用 mac 地址 / 物理地址

mac 地址做到了每个设备都是唯一的 (每个网卡都是唯一的),是在网卡出厂的时候就写死了

例如,以太网网卡的物理地址:
物理地址… … … … . . : 00-EO-4C-8D-46-E6
蓝牙网卡的物理地址~
物理地址… . . … . . . …: 74-4C-A1-76-26-D4

物理地址,也不是完全不能改,有些网卡是支持手动配置的

已经有 IP 地址了为什么还要物理地址??
这是一个美好的误会!!!
当年网络层协议和数据链路层协议,是各自独立研发出来的!!!
mac 地址 和 IP 地址,就有点重复了 (按理来说,一套地址就够了)

现在的现状,就是当前 mac 地址 和 IP 地址同时使用,表示不同的功能,

  • IP 用来表示一次传输过程中的起点和终点 (不考虑 NAT 的情况,一个 IP 数据报中的源 IP 和 目的 IP 是固定的)
  • mac 用来表示传输过程中,任意两个相邻节点之间的地址 (一个以太网数据帧,在每次转发过程中,源 mac 和 目的 mac 都会改变)

类型:

  • 0800:一般情况,完整的 IP 数据报
  • 0806,8035:特殊的情况

CRC:

帧尾就是一个基于 CRC 算法的校验和,循环冗余算法:把数据的每个字节依次讲行累加 (溢出就溢出,没关系)

46-1500:

  • MTU. 一个以太网数据帧能够承载的数据范围,这个范围取决于硬件设备
  • 以太网是和硬件也密切相关的。但是其他的硬件设备,对应的数据链路层协议,可能又不一样,MTU 也不相同
  • 数据链路层考虑的是,相邻节点之间的数据传输
    考虑这个细节的时候就需要关注到交通工具是啥,不同的交通工具,能够搭载的数据量就不太相同
  • 如果数据报超过了 MTU 怎么办?
    IP 层能够分包,IP 层的分包其实不是给 IP 的报头 64k 准备的…更多的是为了适应数据链路层的 MTU

3、MTU

MTU 相当于发快递时对包裹尺寸的限制。这个限制是不同的数据链路对应的物理层,产生的限制

  • 以太网帧中的数据长度规定最小46字节,最大1500字节,ARP数据包的长度不够46字节,要在后面补填充位;
  • 最大值1500称为以太网的最大传输单元(MTU),不同的网络类型有不同的MTU;
  • 如果一个数据包从以太网路由到拨号链路上,数据包长度大于拨号链路的MTU了,则需要对数据包进行分(fragmentation);
  • 不同的数据链路层标准的MTU是不同的

MTU对IP协议的影响:

  • 由于数据链路层MTU的限制,对于较大的IP数据包要进行分包
  • 将较大的IP包分成多个小包,并给每个小包打上标签;
  • 每个小包IP协议头的 16位标识(id) 都是相同的;
  • 每个小包的IP协议头的3位标志字段中,第2位置为0,表示允许分片,第3位来表示结束标记(当前是否是最后一个小包,是的话置为1,否则置为0);
  • 到达对端时再将这些小包,会按顺序重组,拼装到一起返回给传输层;
  • 一旦这些小包中任意一个小包丢失,接收端的重组就会失败。但是IP层不会负责重新传输数据;

MTU对UDP协议的影响:

  • 一旦 UDP 携带的数据超过1472(1500 - 20(IP首部) - 8(UDP首部)),那么就会在网络层分成多个IP数据报。
  • 这多个IP数据报有任意一个丢失,都会引起接收端网络层重组失败。那么这就意味着,如果UDP数据报在网络层被分片,整个数据被丢失的概率就大大增加了

MTU对于TCP协议的影响:

  • TCP 的一个数据报也不能无限大,还是受制于MTU。TCP的单个数据报的最大消息长度,称为MSS(Max Segment Size);
  • TCP在建立连接的过程中,通信双方会进行 MSS 协商。
    • MSS:TCP 中在 IР 不分包的前提下,做多搭载多少载荷
      MTU 也取决于 TCP 和 IP 的报头(报头都是变长的)
  • 最理想的情况下,MSS的值正好是在IP不会被分片处理的最大长度(这个长度仍然是受制于数据链路层的MTU)。
  • 双方在发送SYN的时候会在TCP头部写入自己能支持的MSS值。
  • 然后双方得知对方的MSS值之后,选择较小的作为最终MSS。
  • MSS 的值就是在TCP首部的40字节变长选项中(kind=2);

MSS和MTU的关系:

分包的开销还是有的,MSS 对于 TCP 起到一定的提示效果,当当前传输 TCP 的数据长度不超过 MSS 的时候,是属于最高效的状态

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制


4、ARP 协议

虽然我们在这里介绍ARP协议,但是需要强调,ARP不是一个单纯的数据链路层的协议,而是一个介于数据链路层和网络层之间的协议,不是用来传输数据的,只是起到一个辅助的效果

路由器这样的设备在转发数据的时候,首先拿到的是一个 IP 地址(目的 IP),通过 IP 地址来决定接下来这个数据如何走 (从哪个端口出去,发到哪个设备上),因此就得决定,接下来封装的以太网数据帧,目的 mac 是什么。

需要根据 ARP 协议,建立起 IP -> mac 这样的映射关系 (类似于 hash 表这样的键值对结构)

但是这个表不一定是在内存里,也可能是直接在硬件中存储,
当设备启动的时候,就会向局域网中,广播 ARP 报文,每个设备收到之后,都会给出一个应答,
应答的信息中就包含了自己的 IP 和 mac
发起广播的那一方,就可以根据这些回应,建立起这个映射表了

例如:我想统计每个同学的邮箱,我就群里喊一声,都把自己的名字和邮箱,私信给我,大家收到这个广播消息,就纷纷私信,然后我把这个得到的结果,整理到一个表格上


八、应用层协议补充

  • DNS 是一个应用层协议
  • DNS,即Domain Name System,域名系统。DNS是一整套从域名映射到IP的系统。
  • TCP / IP 中使用 IP 地址来确定网络上的一台主机,但是 IP 地址不方便记忆,且不能表达地址组织信息,即使写成了点分十进制,于是人们发明了域名,并通过域名系统来映射 域名和 IP 地址
  • 域名 和 IP 地址之间,是一个一一对应的关系

域名是一个字符串,如 www.baidu.com

域名系统为一个树形结构的系统,包含多个根节点。其中:

  1. 根节点即为根域名服务器,最早 IPv4 的根域名服务器全球只有13台,IPv6 在此基础上扩充了数量。

  2. 子节点主要由各级 DNS 服务器,或 DNS 缓存构成。

    • DNS域名服务器,即提供域名转换为IP地址的服务器。

    • 浏览器、主机系统、路由器中都保存有DNS缓存。

    • DNS系统,最开始的时候,只是一个普通的文件,称为 hosts 文件

      Windows 系统的 DNS 缓存在 C:\Windows\System32\drivers\etc\hosts 文件中,
      Mac/Linux 系统的 DNS 缓存在 /etc/hosts 文件中。

      这个是最早的域名解析系统:

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

140.82.114.3 github.com:每一行,就描述了 IP 和 域名 之间的关系,后续再其他程序(浏览器)中使用这个域名,就会被自动转换成 IP 地址

现在,hosts 文件已经不再使用了(虽然仍然是好使的),全世界的域名那么多,总不能天天在这对这个 hosts 改来改去,

干脆,就专门成立一个机构,负责维护这里的 域名 和 lP 的应对关系,比如你要申请一个域名,就去这个机构报备即可

这个机构维护一组服务器,把 hosts 文件存到这个服务器里,域名解析服务器 —— 根 域名解析服务器
你自己的电脑想要进行域名解析,就访问一下这个人家的服务器就行了

全世界的设备这么多,每个设备上网,都要去访问这个域名解析服务器嘛? 域名解析服务器不会压力很大嘛??
全世界各个地方的国家,地区,城市,有各自的网络运营商,这些网络运营商会就近架设 域名解析 镜像 服务器
咱们平时上网的时候,一般就是就近访问了咱们的镜像服务器

日常生活中就会遇到一种场景:QQ 能上,但是网页打不开,是直接写死的 IР 地址来访问 QQ 的服务器,不涉及域名解析

网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

勾选了自动获取,其实就是从运营商这里获取 (也就是运营商的域名解析服务器),手动改成其他的域名解析服务器就可以了

当我们的主机,查询了一次 DNS 之后,主机就会把这个查询结果缓存一定的时间 (浏览器来进行缓存)
下次再访问到同一个域名的时候,就可以省略查询 DNS 的过程了,因为 DNS 域名 和 IP 的对应关系,是很少变化的


相关文章

暂无评论

暂无评论...