目录
[1. 传输层](#1. 传输层)
[1.1 端口号](#1.1 端口号)
[1.2 UDP协议](#1.2 UDP协议)
[1.2.1 UDP协议端格式](#1.2.1 UDP协议端格式)
[1.2.2 UDP协议的特点](#1.2.2 UDP协议的特点)
[1.3 TCP协议](#1.3 TCP协议)
[1.3.1 TCP协议段格式](#1.3.1 TCP协议段格式)
[1.3.2 确认应答](#1.3.2 确认应答)
[1.3.3 超时重传](#1.3.3 超时重传)
[1.3.4 连接管理](#1.3.4 连接管理)
[1.3.5 滑动窗口](#1.3.5 滑动窗口)
[1.3.6 流量控制](#1.3.6 流量控制)
[1.3.7 拥塞控制](#1.3.7 拥塞控制)
[1.3.8 延时应答](#1.3.8 延时应答)
[1.3.9 捎带应答](#1.3.9 捎带应答)
[1.3.10 面向字节流](#1.3.10 面向字节流)
[1.3.11 异常情况](#1.3.11 异常情况)
[1.3.12 TCP和UDP对比](#1.3.12 TCP和UDP对比)
[2. 网络层](#2. 网络层)
[2.1 IP协议](#2.1 IP协议)
[2.2 地址管理](#2.2 地址管理)
[2.2.1 网段划分](#2.2.1 网段划分)
[2.2.2 特殊的IP地址](#2.2.2 特殊的IP地址)
[2.2.3 IP地址的数量](#2.2.3 IP地址的数量)
[2.3 路由选择](#2.3 路由选择)
[3. 数据链路层](#3. 数据链路层)
[3.1 认识以太网](#3.1 认识以太网)
[4. 应用层协议](#4. 应用层协议)
[4.1 DNS协议](#4.1 DNS协议)
1. 传输层
负责把数据从发送端传输到接收端。
1.1 端口号
端口号是用来表示一台主机上的不同的进程。
端口号的范围划分:
0~1024:是一些知名端口号,比如说http协议,https协议等这些协议的端口号就是固定的。
1024~65535:操作系统动态分配的端口号,客户端上的应用程序的端口号,就是操作系统在这个范围内分配的。
http服务器端口号是:80.
https服务器端口号:443
1.2 UDP协议
1.2.1 UDP协议端格式

报头的长度为8个字节,每个属性各占2个字节。
**长度:**指的是整个UDP数据报的长度,这个长度的属性占2个字节,表示的范围是0~65535,也就是64KB。
**载荷:**就是完整的应用层数据包。
**校验和:**用来验证数据是否发生修改。
数据的传输是通过光信号或者电信号或者电磁波信号来进行传输的,如果这些信号受到环境的干扰就有可能造成数据的比特位翻转,导致传输的数据错误。
发送方在发送数据之前会根据除了校验和之外的数据,计算出来一个校验和,将校验和和数据发送出去,接受方拿到数据后,会重新计算一下校验和,看是否相同,相同就接受,不同就丢弃。
UDP的校验和计算使用的是CRC的方式来进行校验和的计算,把每个字节都当做一个整数(除了校验和的其他数据),然后累加起来,最后得到一个校验和。
如果两个相同的原始数据通过相同方式计算出来的校验和是一样的,但是两个数据的校验和一样,不一定原始数据一样,有一种很小的概率原始数据发生了比特翻转,但是最后计算的校验和还是一样的。
1.2.2 UDP协议的特点
无连接:知道对端的IP和端口号就直接传输。
不可靠传输:数据发出去之后就不再管了,发生丢包或者数据错误也不会再重传数据。
面向数据报:不能灵活的控制读写数据的次数和数量。
随着时代的发展,UDP数据报的64KB大小已经不能满足数据传输的需求了,而是需要复杂的拆包和组装来传输大的数据了。
1.3 TCP协议
1.3.1 TCP协议段格式

32位序号:是由发送端填入自己发送的数据的第一个字节的序号,告诉接收方自己发送的数据从哪里开始。
32位确认序号:当ACK为1时候有效,接收方告诉服务器下次发送数据从多少序号开始发送。
4位首部长度:表示TCP的报头的长度,单位是4字节,最大长度为60字节。
保留(6位):这里是预留的位置,如果后续TCP的长度不够用就可以使用保留位。
6位标志位:
URG:紧急指针位,相当于优先出来该数据。
ACK:确认号字段有效,表示已经成功接收到数据。
PSH:催促标志位,接收方要立即处理这个数据。
RST:对方要求重新建立连接,复位报文段。
SYN:用于请求建立连接,同步报文段。
FIN:用于断开连接,结束报文段。
16位校验和:通过使用CRC方式计算TCP的首部和数据部分的校验和,来确保数据的正确传输。
1.3.2 确认应答
为了保证TCP的可靠性,发送方在发送出去数据后,需要对方回复一个"应答报文"(ACK),来让发送方知道接收方是否拿到了数据。
但是存在一些问题,如果发送方发了很多条数据,接收方拿到的数据有可能是乱序的,不能得到原始数据,因为TCP协议是面向字节流传输数据的,数据在传输时候,走的路线可能不同,可能会发生后发先到的情况,此时接收方不能根据乱序的数据得到原始数据,如果部分数据丢失,发送方和接收方也不知道那些数据丢失了,如何让发送方知道,接收方已经收到了那些数据呢?
这里TCP协议对数据进行了编号,按照字节来进行编号,一个字节对应一个编号。
为了保证接收方读到的数据的顺序和发送方接收的数据的顺序是一样的,TCP协议会在接收方这里设置一个"接收缓冲区",帮我们对数据进行排序,读取数据时候,先读取小的序号的数据,如果小序号数据没有到达,就会阻塞等待,知道读取到正确序号的数据。
当发送方进行数据发送时,会将发送数据的第一个字节的序号,填写在TCP首部中的序号中,当接收方发送应答报文时候,会将接收到的数据的最后一个字节的序号 + 1,填写在应答报文中的首部的确认序号中,告诉接收方下一次从那个序号开始发送数据。

1.3.3 超时重传
这个机制是用来解决丢包问题的。
为什么数据在传输过程中会丢包呢?
数据在传输过程中,可能碰到一个繁忙的路由器或者交换机,此时这个路由器已经忙不过来了,此时就会对新接受的数据进行丢弃,这就导致了丢包问题。
丢包问题的两个情况:
-
发送方发送的数据丢失。
-
接收方发送的ACK丢失。
发送方会引入了一个超时时间,来判断是否发生丢包问题:
如果发送方在这个时间内没有接收到接收端发送的ACK,就会认为是出现丢包问题,就会重新发送一份数据。
如果是接收端发送的ACK丢失了,那么发送端就发送了重复的数据,此时TCP的接收端就会在接收缓冲区中根据序号进行去重操作,重复的序号数据直接丢弃。
每次超时重传后,发送端就会上调这个数据的超时时间阈值,但是不会一直上调,达到上调次数后,发送端就会放弃发送该数据了。
1.3.4 连接管理
建立连接:
TCP的建立连接过程是通过 三次握手 来实现的。
A 和B要建立连接,A先给B发送SYN报文,这里的SYN设置为1表示这次数据是同步报文,告诉B要跟它建立连接,然后让B保存好A的信息,接着B给A发送一个ACK来表示B收到了A的数据,并且B会发送SYN给A,当A接到B的数据后,给B发送一个ACK报文来表示A接收成功。
这就是三次握手的过程。

客户端和服务器建立连接过程中会存在不同的状态。
closed:不属于TCP的一种状态。
listen:表示服务器已经启动起来,随时可以接收客户端的连接。
established:表示连接已经建立起来,可以传输数据了。
为什么TCP要进行三次握手?
为了确定数据传输的网络链路是通畅的。
为了验证通信双方的发送能力和接收能力是正常的。
三次握手过程中,通信双方可以协商一些关键信息,比如说初始序列号。
客户端第一次发送SYN时候,可以定好一个初始序列号ISN1,告诉服务端客户端发送的数据从ISN+1序列号开始发送,服务器接收到建立连接请求后,发送SYN并且也会生成一个序列号ISN2,发送给客户端,告诉客户端,服务器会从ISN2+1序列号开始发送数据,然后客户端会发送一个SYN告诉客户端,自己已经收到请求。
为什么两次连接的初始序列号不设置一样的呢?
因为如果第一次连接发送的数据发生阻塞,在建立第二次连接时候,第一次连接发送的数据发送到了,此时就会导致数据错误。
四次挥手:
断开连接是通过四次握手 机制来完成的。

A是客户端,B是服务器。
客户端先给服务器发送FIN报文来请求断开连接。
然后服务器发送ACK报文表示收到请求。
服务器给客户端发送FIN表示断开连接。
客户端给服务器发送ACK报文表示收到请求。
为什么这里的四次挥手不能是三次挥手呢?
因为这里的FIN报文是通过代码来实现返回的,而ACK报文是由操作系统的内核来第一时间返回的,SYN报文也是由操作系统内核来返回的。所以FIN报文和ACK报文不能同时返回。
如果代码中使用了延时应答的机制,刚好和B的FIN报文返回时间一致,就可以一起返回给客户端。

这里左边是客户端,右边是服务器。
客户端首先发送FIN报文,然后进入FIN_WAIT_1状态。
然后服务器接收到FIN报文,并发送ACK报文,此时进入CLOSE_WAIT状态。
在CLOSE_WAIT状态时候,此时服务器还可以继续发送数据,直到发送完毕。
服务器再发送FIN报文,进入LAST_ACK状态。
客户端接收到FIN报文,回复ACK报文,进入TIME_WAIT状态,过一会客户端关闭。
服务器接收到ACK报文之后,立即关闭。
这里的客户端的TIME_WAIT状态是:客户端发送了ACK报文,但是不会立即关闭,而是等一会关闭,为什么呢?
因为有可能客户端发送的ACK报文数据丢失,导致服务器没有收到,此时服务器有可能重新传FIN报文,此时客户端接收到报文就会重新发送ACK报文。这里客户端也不能一直等下去,会有一个等待时间,默认是60s或者120s,这个时间足以包括,服务端重新发送一个FIN报文到达客户端的时间了。
1.3.5 滑动窗口
由于TCP协议为了确保可靠传输,导致该协议的传输效率较低,为了提高这个效率,TCP协议引进了一个滑动窗口的概念。
让客户端连续发送多个数据,不用等到服务器返回ACK,等到连续发送一定量后,再等待接收ACK报文,滑动窗口就是能够连续发送数据的最大数据量。

主机A连续发送4000个字节的数据,然后开始接收主机B发送的ACK报文,接受一个接着发送下一个。这里发送方需要设置一个发送缓冲区,收到ACK报文的数据都从缓冲区中删除掉。
滑动窗口不能过于大,是在可靠性的前提下提高效率。
滑动窗口过程中也会出现丢包现象,丢包后如何进行重传呢?
第一种情况:
客户端发送的数据包丢了

如果1001~2000数据丢了,此时服务端会一直发送1001的ACK报文,如果客户端连续三次接收到该报文就会重传1001~2000的数据,此时服务端返回的报文就直接从7001开始,因为这之前的数据已经传输过去了,只差一个1001。
该机制也叫做快速重传。
第二种情况:
服务端发送的ACK报文丢了

这种情况,可以直接根据后面的ACK报文来确定,不需要重传。
1.3.6 流量控制
接收端接收数据的能力是有限的。客户端发送数据到接收缓冲区中,服务端从接收缓冲区拿数据进行处理,如果客户端发送数据的速度太快,导致服务端处理不过来,导致接受缓冲区满了,此时就需要进行流量控制。
这里就涉及到TCP报头的一个属性16位窗口大小,该属性接收方用来返回缓冲区剩余可接收数据的大小,客户端可以根据这个属性来调整滑动窗口的大小。
16位窗口大小不代表最大是64KB,在TCP报头的选项里面有一属性,窗口拓展因子,相当于根据这个属性将窗口大小左移几位,指数的增长大小。
窗口探测包:
如果接收方满了,此时发送方就会等待,但也不会一直干等,发送方会发送一个窗口探测包来询问接收方可以继续发送了吗,主动询问才会知道能否继续发送。
1.3.7 拥塞控制
虽然TCP协议可以通过滑动窗口来提高效率,但是一开始滑动窗口不能太大,因为数据传输过程中会经过很多计算机,如果一台计算机已经很忙碌了,此时接收到数据就会更加处理不过来,因此TCP协议引入了慢启动的机制。

这里引入了一个"拥塞窗口"的概念:
开始将窗口设置为1,每收到一个ACK应答,窗口就+1,每次客户端发送数据时候,会先比较拥塞窗口大小和服务器返回的窗口大小,取最小值作为实际窗口大小发送数据。
刚开始拥塞窗口是慢启动,这里的慢启动是按照指数来进行增长的,达到慢启动的阈值时候就会开始线性增长。
当开始遇到少量丢包时候,就会触发快速重传机制,每快速重传一次就会让慢启动的阈值减少一半,然后发送方的拥塞窗口就会每收到一个ACK,拥塞窗口+1,在接收到重传数据的ACK报文后拥塞窗口就变为慢启动的阈值大小开始传输数据。
1.3.8 延时应答
服务器在返回ACK报文时候,也可以不用立即返回,返回报文中包含了接收缓冲区的可以接收的大小,有时候延时发送ACK报文,可能会让该窗口大小变大,有可能延时的时间,服务器就处理了很多数据。
这里的延时应答也不是每返回一个ACK就延时应答一次,而是根据具体情况来确定的:
数量限制:可以设置在N次请求后延时应答一次。
时间限制:可以设置达到最大延时时间后延时一次。
1.3.9 捎带应答
捎带应答是在延时应答的基础上引出的,本来返回ACK和响应的时机不是一起的,但是引入延时应答后,ACK在延时应答后,此时可以和响应一起发送给客户端,减少服务器的发送次数,这样就也能提高效率。
1.3.10 面向字节流
TCP协议是面向字节流的,这里就会在应用层数据产生一个粘包问题。
当不同的包的字节流数据在应用层如何进行区分?
方法一:
通过约定特殊字符来作为包和包之间的分割,比如利用\n来分割。
方法二:
设置前面四个字节表示数据包的长度来进行区分。
1.3.11 异常情况
进程崩溃:
此时会释放文件描述符表,仍然能正常发送FIN触发四次挥手,断开连接。
主机关机:
此时客户端A进行关机操作,关机时间内,会进行四次挥手操作,关机前执行完就断开连接。
如果关机了还没执行完四次挥手,此时服务端发送FIN不会收到客户端的ACK,此时服务端就会多次发送,达到一定次数后,就会停止发送,自动断开连接。
主机掉电/ 网线断开:
如果是发送方掉电,此时接收方就一直收不到数据,过一段时间,接收方就会发送一个心跳包,来判断发送方是否正常,如果没有收到ACK报文,就会主动释放了连接。
如果是接收方掉电,此时发送方一直收不到ACK,就会发送一个RST(复位报文),然后复位报文没有收到ACK,此时发送方就会自动断开连接。
1.3.12 TCP和UDP对比
TCP用于可靠传输的情况,比如:文件传输,重要状态更新等情况。
UDP用于传输效率快,实时性要求高的领域,对于视频传输等。
2. 网络层
2.1 IP协议
IP协议主要做的工作就是地址管理和路由选择。
协议头格式:

4位版本号:用来执行IP协议的版本,实际上只有IPv4和IPv6两个版本。
4位首部长度:表示的IP协议的报文长度,单位是4字节。
8位服务类型:3位优先权字段已经弃用,一位保留字段(必须置为0),四位TOS字段:最小延时,最大吞吐量,最高可靠性,最小成本,每次只能选择一个置为1使用,可以切换状态。
16位总长度:表示IP数据报整体占用的长度,最大64KB。
如果超过64KB的数据,IP协议会拆分成多个IP数据报发送,最后接收方再组包。
16位标识:表示同一个数据拆出来的数据报的标识位设置成一样的,组包时候相同标识位的包组合在一起。
3位标志:第一位标志位是保留标志位,第二位标志位是表示该IP数据报是否拆包了,第三位标志位表示该拆包的数据报是不是最后一个拆的包。
13位片偏移:用来表示拆包后的包的编号,组包时候按照编号来组包。
8位生存时间:这个表示数据传输到目标主机的最大传输时间,这里时间单位是次数,每经过一个路由器的传输,TTL-1,最后TTL=0还没传输到,就会丢弃该数据。
8位协议:表示传输层使用的那个协议类型。
16位首部校验和:用来校验IP的报头部分是否传输正确。
2.2 地址管理
2.2.1 网段划分
IP地址包含两个部分:
**网络号:**用来区分两个相互连接的不同网段。
**主机号:**用来区分同一个网段下的不同主机。
子网掩码: 用来区分网络号和主机号,也跟IP地址一样分成4个字段,通过与IP地址字段按位与操作,得到的结果就是网络号,主机号的数量是子网掩码对应位的值被256减去得到的值。表示那个比特位是网络号。
比如:

同一个局域网下,网络号必须相同,主机号必须不同。
相邻局域网下,网络号必须不同,主机号没要求。
2.2.2 特殊的IP地址
IP地址的主机地址全部设置为0,就称为网络号,表示这个局域网。
将IP地址的主机地址全部设置为1,成为广播地址,用于给同一个链路的所有主机发送数据包。
127.*的IP地址用于本机环回测试,通常是:127.0.0.1
主机号为1的IP一般作为网关IP。
2.2.3 IP地址的数量
IP地址的长度为4字节32位,也就是2^32-1种IP地址,大概是43亿多,现实中每一个网卡都要分配一个或者多个IP地址,但是IP地址的数量就那么多,不够用怎么办?
方法一(动态分配):
这种方法只有在设备使用时候才分配IP地址。
方法二(NAT网络地址转换):
NAT将IP地址分为两种 公网IP和 私网IP,公网IP不可以重复,但是不同公网下的私网IP可以重复。
RFC组织规定下面IP地址才可以用于私网IP地址:
10.*,前8位是网络号,可以表示16 777 216个地址。
172.16. ~ 172.31.,前12位是网络号,共1048 576个地址。
192.168.* 前16位是网络号,共65536个地址。
上面范围之外的全是公网IP。
NAT规则约束下,网络通信如何进行的?
同一个公网下的设备之间可以相互通信。
公网A和公网B之间可以互相通信。
不同局域网下的设备之间不能直接通信。
公网设备A不可以访问局域网设备B
局域网设备A可以访问公网设备B。

当私网发送的数据经过公网路由器时候,会把数据里面的IP地址和端口号换成该路由器的,再发送出去,路由器接收到数据后会将数据里面的自己的IP地址和端口号换成之前的,发送给私网的机器。
这里路由器要记录下原来的IP和端口号,与新的IP和端口号的映射关系。
方法三(使用IPv6):
IPv6是在原来的IPv4的基础上,将长度扩大至16字节,128个比特位,这个能表示的IP地址的数量就是一个天文数字。
2.3 路由选择
当IP数据包到达路由器后,该路由器会先在自己的路由表(用来记录该路由器周围路由器的IP地址以及需要从那个口转发过去),如果没有找到,就跳转到上一级路由器,接着寻找。每跳一级路由器,路由器的路由表包含的信息越多,越容易找到,如果找到了,就会直接从该路由器保存的该IP的发送端口转发出去。
3. 数据链路层
3.1 认识以太网
以太网是数据链路层和物理层的协议,它规定了设备之间如何通过网线如何传输数据,我们平常用到的网线也叫做以太网线。
以太网数据帧的格式:

目的地址和源地址:这里的地址指的是物理地址,也就是mac地址。
mac地址是数据链路层设置的地址,该地址大小有6字节,所有可以确保每个网卡分配一个mac地址,每个网卡在出厂时候就会设置好一个固定的mac地址,因此mac地址也可以定位的每台机器上,mac地址主要是用来在数据链路层中使用的,主要用于进行相邻两个设备之间的通信,mac地址的样式是每个字节之间用:分隔。
类型:不同的类型对应不同的以太网数据帧的载荷。
以太网数据帧的载荷最大为1500字节,也就是1KB多点的大小,而IP数据包最大为64KB,但是由于以太网数据帧太小,所以IP数据包就会达到1500字节大小就会进行拆包来传输。
CRC:也就是校验和,来确保以太网数据帧的传输正确。
ARP请求:该请求是用来辅助以太网协议的,根据ip地址得到对应的mac地址。
如果mac地址全为1就是广播地址,此时该地址的路由器,就会向附近的路由器发送ARP请求,询问对方的ip地址和mac地址是多少,每个路由器都会存在一个哈希表,用来记录ip地址和mac地址的对应关系,只有得到mac地址,才能进行数据链路层的以太网数据帧的填写,进而传输数据。
4. 应用层协议
4.1 DNS协议
TCP/IP协议使用IP地址和端口号来确定一台主机,但是这个ip地址不太好记忆,后来就引入了域名的概念,域名本质就是一个字符串,将每个域名对应一个ip地址,并使用hosts文件来记录域名和ip地址的对应关系,比如 www.sougou.com就是搜狗的域名,而它就对应搜狗的ip地址。
而DNS协议就是用来将域名解析成对应的ip地址,来进行访问对应的服务器的,随着域名的越来越多,hosts文件存储的方式已经不能满足现实需求,后来就产生了DNS服务器,专门用来解析域名的。
全球共有11台根服务器,但是这些服务器同时要为全球用户提供服务,就会导致巨大的高并发数量,此时就有挂的风险,如何解决呢?
-
当我们第一次访问一个域名时候,从DNS服务器找到对应的ip地址,此时就会在本机缓存里面存储该域名对应的ip地址,下次访问时候,就不用访问DNS服务器了。
-
各大公司可以搭建镜像DNS服务器来实现DNS的服务,就可以减轻根服务器的压力。