计算机网络八股文复习
基础篇
- OSI 七层模型
- 应用层:在这一层会有很多应用协议,HTTP、FTP、DNS、SMTP
- 表示层
- 会话层
- 传输层:TCP、UDP在这一层
- 网络层:IP协议
- 数据链路层:MAC
- 物理层
DNS解析
所谓的DNS解析,就是服务发现的过程,就是找到你想访问的服务器的Ip地址和端口号。
DNS就是保存了域名和对应IP地址的服务器。

通过这张图就能看出来,首先去访问是最高级别的根DNS服务器,然后一层一层往下访问,最后找到www.baidu.com,找到之后就是发送对应的请求获得想要的数据
TCP篇
TCP是一个面向连接、可靠的、基于字节流的通信协议
面向连接:TCP是一个面向连接的协议,它不像UDP可以对多个主机发送信息,基于TCP,建立连接之后只能对应一个主机发送信息。
可靠的:TCP有多个方法保证信息不丢失。
基于字节流的:因为一个TCP消息,会被切割成多个报文发送,如果接收方没有接受到发送方传来的上一个报文,就会一直等待,接下来接收到有重复的包也会丢弃
TCP的头部

从这张图中,我们能看出TCP头部的重要组成部门
- 源端口号和目标端口号,IP地址是放在IP报文中的
- 序列号,TCP是面向连接的,在发送一个TCP报文的时候,会叠加这个序列号,表明这个报文顺序
- 确认应答号,TCP是面向连接的,也就是两个主机之间的传送,确认应答号的作用是,表明在这个应答号之前的数据都被接受了
- 首部长度,因为TCP头部不是定长的,就设计这个首部长度来表明长度
- 校验和是用来验证TCP的数据安全性的
- ACK,确认应答,除了建立连接的阶段,其余阶段都为1
- RST,表明TCP出现异常了,这个时候必须强制断开连接
- SYN,表示想建立连接
- FIN,表示连接中断
TCP与UDP的区别
UDP首部

- 从这儿能看出UDP的首部大小要小很多,这说明从首部开销的角度来讲,UDP要小很多
- TCP传输需要连接而UDP不需要
- TCP是流失传送数据而UDP是按包传送,包可能会乱序
- TCP保证数据可靠,而UDP是不能保证的
- TCP是面向连接的也就是点对点的,而UDP是一对多的
- TCP有拥塞控制、流量控制等手段,而UDP不会随着网络堵塞而降低他的发送速率。
TCP的三次握手
都知道TCP是面向连接的,那这个连接是如何建立的呢
第一次握手

- 这是客户端发送的报文,首先客户端会随机初始化一个序列号,后续客户端的发送,都是在这个序列号上叠加。设置SYN为1
第二次握手

服务端发送的报文,返回的ACK,让客户端知道自己发送没有问题,返回SYN是表名服务端也想和客户端建立连接。返回的确认应答号表名,在这个序列号之前的数据都被正常接受了,服务端也会生成一个序列号,让后续自身发送的包不会乱序。
第三次握手

第三次握手就正式建立连接了,返回确认应答号表名服务器发送的数据包被正常接受了。这次请求可以携带数据!
那么问题就来了,为什么不是两次握手,一定要三次握手呢?
原因:三次握手才能保证双方都有发送和接受的能力,并且三次握手能阻止重复历史连接的初始化
- 三次握手是如何组织重复历史连接的初始化的?
首先我们要明白,ESTABLISHED这个状态。正常的三次握手,在客户端发送第三次TCP报文的时候,客户端处于ESTABLISHED状态,而服务端接受报文的时候,变成ESTABLISHED状态。
此时模拟一个情况,客户端发送一个请求建立连接的报文,SYN+SEQ=90,此时客户端宕机,重启后再次发送请求建立连接的报文SYN+SEQ=100,此时服务端接受到就的请求,返回SYN+ACK+ACK_SEQ=91+SEQ_SERVER=400,此时客户端接受到这个TCP报文之后,通过上下文判断这是一个非法的请求,就能终止这次的TCP链接,而如果是一个两次连接,在服务端发送完报文之后,就处于ESTABLISHED了,这明显就浪费了服务端的资源。
如果第一次握手丢失
客户端重传
如果第二次握手丢失
客户端重传
服务端重传
第三次握手丢失
服务端重传
TCP三次握手状态机流转。

- 初期客户端、服务端处于close状态。接着服务端开始监听端口,处于Listen状态
- 客户端发送SYN=1+SEQ=1的请求报文至服务端,客户端处于SYN_SENT状态,服务端接收到报文之后,返回响应报文,SYN=1+ACK_SEQ=2+SEQ_SERVER=1,之后服务端处于SYN_RECIVE状态。
- 客户端接收到SYN=1+ACK_SEQ=2+SEQ_SERVER=1的报文后,自身处于ESTABLISHED状态,然后返回ACK=1+ACK_SEQ=2+SEQ=2的报文,客户端接收到之后,更新自身状态为ESTABLISHED.
这也是为什么只有第三次的发送能够携带信息的原因,因为其余两次就算建立成功了,两边的链接也没有建立起来,而第三次状态机建立起来之后,两边就能通信了。
TCP的四次挥手
四次挥手的流程相对来说就简单很多
-
客户端发送FIN=1的报文,表明,客户端没有数据需要发送了,但是还可以接受数据
-
服务端发送ACK表明确定
-
服务端发送FIN=1的报文表明,服务端没有东西要发送了,再等待客户端最后的确认
-
客户端发送最后确认
四次挥手的状态机流转

-
初期客户端发送端都处于ESTABLISHED状态,客户端发送FIN报文,自身处于FIN_WAIT_1状态
-
服务端接收到消息,返回ACK,服务端进入CLOSE_WAIT状态,在这个状态中,会把没有发送完的信息全部发送完,客户端接受到ACK之后,自身处于FIN_WAIT_2状态。
-
服务端发送完信息后,发送FIN状态,然后CLOSE
-
客户端接受FIN状态后,进入TIME_WAIT状态,等待一段时间后关闭 。
为什么有TIME_WAIT
首先明确TIME_WAIT的时间是2MSL,MSL为报文存在最长时间,通过限制这个时间,让这个连接中的数据传送完毕,避免影响下个连接。
TCP的滑动窗口
在TCP中定义了滑动窗口的概念,在这个窗口内的TCP报文可以自由发送,只要发送方按时收到确认应答即可,这样即使中间某些ACK丢失也不会触发多余的重传。

如图,因为收到了ACK700,因此明白0~699的数据都被撑场接受了。
TCP的流量控制
流量控制有两种方法
- 停止等待,发送一个TCP报文,等待响应 ,响应了才会发送下一个TCP报文,这明显损耗太大了。
- 滑动窗口,通过滑动窗口,两边都有可用的窗口分别对应发送窗口和接受窗口,比如两边对应200的窗口大小,此时发送端发送一个80大小的数据(期间剩余的120是想法就发的状态),只有当接受端收到80这个这个ACK=81才会向后移动80
TCP的拥塞控制
TCP被设计成一个无私的协议。当网络通道中的数据比较多,比较拥塞的时候,会降低自身的发送速度。对于拥塞控制只要掌握
- 慢启动+拥塞避免:发送从1 2 4 8 这样指数增长,过了一定门槛再平缓下来变成线性增长
- 恢复有两种,窗口调整为1,指数增长,门槛减半。第二种是窗口调整为门槛大小,然后线性增长。
TCP面向字节流
UDP是面向报文的,意思是,一个UDP报文对着一个完整的信息。一个用户在基于TCP发送消息的时候,一条消息会被拆分成多个TCP报文, 发送报文是取决于当前的网络状态的,所以说TCP是面向字节流的而不是报文的。
DNS的解析过程
DNS解析的时候会先看缓存中是否有对应数据
- 看浏览器中是否有对应IP
- 看os内核上有没有存储对应ip
- 看hosts文件上是否存储对应ip
- 看本地的DNS服务器地址的缓存表格中是否有对应IP
如果都没有,www.baidu.com.
首先从.顶级域名
到.com根域名
xx到区域权威DNS服务器上,拿到IP地址
IPV6初识
- 不需要DHCP也能自动分配IP地址
- 传输性能高
- 安全性强
- IPV4的机器是32位,IPV6的机器是128位
DHCP
全程是有UDP,客户端UDP广播自身信息,服务端使用UDP做出响应,其中携带了可用的IP地址等信息
websocket协议
websocket协议是相对于http协议的。它最核心的一点,它是双向的,全双工协议。什么意思举个例子
当我们要实现一个异步消息更新的时候,如果采用的是http,那可能就是定时通过js发起一个请求,从服务器拿回数据后渲染页面。而如果采用websocket就不一样,它是主动从服务器push数据到前端。
-
单工:数据传输只支持数据在一个方向上传输;在同一时间只有一方能接受或发送信息,不能实现双向通信。举例:电视,广播。
-
半双工:半双工数据传输允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;在同一时间只可以有一方接受或发送信息,可以实现双向通信。举例:对讲机。
-
双工:全双工数据通信允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力;在同一时间可以同时接受和发送信息,实现双向通信。举例:电话通信。
URL和URI的区别
- URI是统一资源标识符:他是标识一个资源的
- URL是统一资源定位符:URL不光标识资源,而且还提供了访问的地址。URL是URI的子集
- URL编码(百分号编码):将URL中具有特殊含义的不可打印字符或字符转换为明确且由Web浏览器和服务器普遍接受的表示的字符。
- 一个完整的URL包括哪些部分
- 协议部分,比如http/https
- Ip部分
- 端口部分
- 虚拟目录部分
- 文件名部分
- 参数部分
- 锚部分
TCP相关
TCP是一个全双工的协议
TCP的首部

- 端口号
- 在TCP头部中保留的是端口好。IP地址是在IP层的
- 序列号:用于解决网络中,包乱序的问题
- 序列号必须是随机生成的,且必须每次不一样。
- 防止历史报文被新的TCP连接接受。可以理解为序列号+四元组唯一标识一个TCP连接
- 防止被人造序列号,被黑客攻击
- 确认号:确认号表示,在这个号之前的数据都被正常接受了。
- 控制位
- SYN:TCP建立链接的初期,置为1,表示这个是请求建立连接的报文。
- RST:表示TCP连接出现异常,需要强制断开连接
- FIN:表示TCP的某一方需要断开连接
- ACK:确认应答,除了建立连接的报文,其他报文ACK需要置为1
如何理解TCP是一个面向字节流的协议
首先面向字节流面向报文都是在传输层上面的说法,UDP报文的头一打,在网络层,链路层,不管你传啥,我IP一打,MAC地址一打,把你的报文全分成MTU给你传送过去了。
而UDP是不做切分,把一个完整用户的消息传递给下游的数据链路层,分割成MTU之后,通过IP重新组装,丢失了一个UDP分片,就相当于丢失了一个用户消息,但是一个UTP的报文就是一个用户消息的边界。
而TCP不是,TCP会对用户消息进行切分,所以一个TCP报文不是一个用户的边界。所以TCP会发现粘包的问题,所以需要上层协议定义消息的边界(通过特殊符号,或者固定消息的大小等方法)。
所以在这里也看出为什么TCP需要协商MSS的大小了。如果不写上MSS的大小,全凭着MTU分割消息,一个MTU丢失一个分片丢失,一个IP包的信息都要重传,这个是TCP不能接受的,所以不如协商MSS的大小,让一个TCP报文刚好被一个MTU包裹,这样重传的时候只要重传这个TCP报文就可以了。
TCP连接
如何确定一个TCP连接

- 源地址
- 源端口
- 目标地址
- 目标端口
通过这四个要素组成的一个四元组,能够唯一标识一个TCP连接。
对于IPV4,最大的TCP连接数量为2^48
但是现在TCP和UDP可以监听一个端口是通过一个五元组来实现的
新增协议类型这个字段
TCP的三次握手

- 第一次握手:
- 客户端发送SYN=1,SEQ = 300,的报文。SYN=1表示请求建立链接,SEQ=300是客户端随机生成的。必须随机生成。随后客户端进入SYN_SENT状态。
- 第二次握手:
- 服务端接受到客户端的请求报文,进入SYN_RECE状态。返回报文 ACK=SYN=1,表示收到了客户端的请求报文,并且请求与客户端建立链接。ACK_SEQ=301,表示客户端发送的300序列号的包已经成功接受了。SEQ=400,服务器随机生成一个SEQ发送给客户端。
- 第三次握手:
- 客户端接收到服务器的报文,明确自身发送接受都没有问题,进入Established状态。并且发送报文ACK=1,ACK_SEQ=401,表明接收到服务端发送的消息。服务端接受到之后进入Established状态。
在这里必须说明一点,ACK报文是不会重传的
假设
4. 第一次握手失败,客户端发送的报文丢失:客户端发送完报文之后,自身进入SYN_SENT阶段。期待接收到服务端发送的ACK响应报文。经过一段时间没有接收到后,就重传报文,直至达到限制次数,或者接收到响应。
5. 第二次握手失败,服务端发送的报文丢失:已知ACK报文是不会重传的,此时客户端为接收到ACK报文,因此会重传,服务端发送了SYN报文,没有接收到ACK报文,因此服务端也会重传。
6. 第三次握手失败,客户端发送的ACK报文丢失:服务端未接收到报文,因此会触发重传机制。
第三次握手是可以携带数据的
为什么要设置三次握手,而不是二次握手,四次握手呢?
- 三次握手可以保证双方的可靠通信
- 第一次握手,客户端:不能确认信息,服务端确认客户端发送没有问题,自身接受没有问题
- 第二次握手,客户端:确认自己收发没有问题,服务端收发没问题,服务端确认:客户端发送没有问题,自身接受没有问题
- 第三次握手,客户端服务端都确认自身收发没有问题
- 帮助双方都维护序列号
- 假设只有两次握手
- 客户端发送一个请求,SYN=1,ACK=90,此时客户端宕机,客户端重启后再次发送一个请求SYN=1 ACK=100。如果只是两次握手,服务端在接收到SYN=1 ACK=90的报文自身就会进入Establish状态,此时如果应用程序调用accept()进行读写,就会发生错误(因为这个是不合法的连接)。等到服务端返回的ACK=1 ACK_SEQ=91的报文给客户端,客户端发送RST的时候可能已经迟了,造成了资源不必要的浪费。
TCP四次挥手

- 初始两者都出与Established状态。此时客户端主动断开连接,发送FIN报文,自身进入FIN_WAIT_1状态,服务端接收到客户端的报文后,进入Close_WAIT状态
- 服务器发送ACK报文,客户端接收到ACK后,进入FIN_WAIT_2状态
- 服务器经过一段时间,发送FIN报文,表明服务器可以进行关闭了,服务器进入Last_ACK状态
- 客户端接收到服务器发送的FIN报文,返回ACK,服务器接收到后关闭连接。客户端自身进入Time_Wait状态,最后进过2MSL后客户端连接关闭
注意:当FIN文本重传次数过多,传送放回直接进入close状态
为什么需要TimeWait状态_为什么要等待2MSL?
- 帮助被关闭方能够安全的关闭连接。试想如果没有Time_Wait状态,最后一次回收的ACK报文丢失,那么就会让被关闭方一直处于Last_Ack状态。所以设置了TimeWait状态
- 此外TimeWait状态设置为2MSL是保证链路上没有报文了。历史的报文不会影响下一个新生成的TCP连接,下一次TCP连接建立后,链路上流转的报文皆为新链接生成的报文。
- 关于2MSL的测定:规定的MSL的时间是2分钟(2MSL就是4分钟),但现实中常用30s或者一分钟。MSL的测定是依据TTL来的。所谓的TTL是位于IP报文上的一个字段,规定了一个IP报文从主机发出最多能跳转几个路由,一般来说MSL的时间要大于等于TTL的时间。
建立TCP连接的时候,调用的API
- socket:客户端和服务端通过socket进行初始化
- bind:服务端通过bind绑定ip和端口
- listen:服务端通过listen监听
- connect:客户端通过connect发起连接请求
- accept:建立请求后,服务端通过accept从全连接队列中获取一个连接进行读写
- send
- receive
注意:没有listen可以建立链接
accept,是服务端调用的,从已经连接的全连接队列中选择一个socket读写,不影响连接的建立。
TCP的全连接队列和半连接队列
TCP的半连接队列:当服务端收到了来自客户端的SYN报文,内核就会把这个链接放到半连接队列中,并且返回SYN + ACK报文
TCP的全连接队列:当TCP接收到来自客户端的ACK报文后,会将半连接队列中对应的连接放入全连接中。
TCP的安全措施
为什么说TCP是安全的
- 面向连接
- 他拥有一系列可以帮助他安全的策略
- TCP的头部有序号。因为TCP会被切分成很多个TCP报文,因此通过这个序号进行标记
- ACK机制,在TCP中,如果收到报文,会返回一个ACK位置 = 1,确认号为序列号 + 1的报文
- 重传机制。如果定期没有收到ACK报文会触发重传
- TCP首部有校验和
- 通过滑动窗口来优化了性能
TCP的重传机制
- 超时重传:TCP的报文中有确认应答字段,通常接收端接收到这个确认应答字段后,就明白了,在这个应答字段之前的数据被正式接受了。比如发送端发送一个TCP报文,序列号为100,在长时间没收到接收端返回的TCP报文,确认应答为101的报文,经过一个指定的时间,就会触发超时重传,重新发送这个报文,
- 快速重传:相对来说反应速度会快很多,当发送SEQ=1,成功接受返回ACK=2,发送SEQ=2,成功接受返回ACK=3,但是这个时候SEQ=2丢失了,就不会发送ACK=3,这个时候发送SEQ=3、SEQ=4、SEQ=5会一直返回ACK=2,当ACK=2接受到3次的时候自动触发重传机制。
快传会有一个问题,当发送SEQ=1~SEQ=6的时候,SEQ=2、SEQ=3丢失了,这个时候ACK=2返回了三次,应该选择发送SEQ2之后的所有数据,还是选择发送SEQ2呢?this is question
- SACK重传: 为了应对快速重传的所带来的的问题,接收方可以选择在TCP的头部加入SACK字段,记录接收方接受了哪些数据,这样发送方可以选择没有接收到的数据重新发送。
TCP的滑动窗口和流量控制
滑动窗口
首先要理解一点,就是所谓的滑动窗口本质上位于操作系统提供的一片缓冲区中。
然后就是很核心的一个地方之前一直没弄懂,发送窗口每次下移的规则:
- 假设当前的滑动窗口大小不会发生变化,整体的窗口不变,比如本来的窗口大小为10,发送方发送了6个数据包,此时,发送方发送窗口为6,可用窗口为4,接受方接受到了6个数据包,此时接收方接受6个数据包,返回ack,并且将接受窗口后移6位,发送方收到ack调整发送窗口,后移6位。
- 但实际上,因为是开辟的缓冲区,所以当接受方处于繁忙状态,很难及时去缓冲拉去信息的时候,发送窗口的大小是会发生改变的。比如上面的例子,如果接收方繁忙,可能接收到6个窗口后,将自己的窗口置为0,那此时接收方就算接到了ack也不会继续发送数据
- 滑动窗口还有一个优势就是:当ack 600丢失,如果但是接收方数据正确接受到了,当返回Ack700的时候也认为700之前的数据被正确接受了
- 接收方和发送方的滑动串口大小,基本是发送方按照接收方的大小来调整自身的。所以有时候会有丢包的问题。比如发送方没及时同步接收方的窗口大小,多发送了几个包,那这几个包可能会丢包。
TCP发送窗口
- 当接受窗口为0时,接受方通过一个窗口非0的ack报文,重启接收方的发送,此时这个ack丢失可能会引起死锁。解决方案是,窗口为0的报文,是接收方定期发送给发送方的,如果没有接收到这个报文,发送方会发送一个窗口探测报文去更新自己IDE窗口。

TCP接受窗口

- TCP的头部有一个窗口大小,指的就是接受放的窗口大小。一般来说是要控制发送方的窗口大小等于接受方的窗口大小的。这样才不会超发数据使得资源浪费。
- 一般来每一个socket都会分配一些缓存,这些数据都先写进缓存的,如果机器比较繁忙,没有及时读取数据,缓存中的数据较多会影响窗口的大小。接受方的窗口变小就会使得发送方窗口变小,从而达到流量控制。
拥塞控制
很明显TCP的拥塞控制不是接收方和发送方,而且针对全局的,是从宏观上来看的。
- 慢启动:核心每次收到一个ACK那么拥塞窗口就扩大1(收到2个就扩大2),于是慢启动的过程是是呈指数上升的。
- 拥塞避免:当慢启动的过程达到一个门限的时候,就会触发拥塞避免算法,此时拥塞窗口的增长呈指数增长。
- 拥塞发生:
- 发生超时重传的时候的拥塞发生:拥塞窗口置为一,拥塞门限设置为原来窗口的一半,慢启动->拥塞避免。
- 发生快速重传:采用快速恢复,门限更新为原来1/2
- 快速恢复:
- 门限设置为 1/2
- 窗口 = 门限 + 3
- 收到一个ACK窗口+1 直至收到新的数据的ACK
- 窗口变为 门限大小
我的理解快速恢复窗口门限+3和收到一个ack窗口+1本质上都是想快点补齐丢失的报文。
TCP粘包问题
一个完整的用户消息会被TCP切分成很多包。这可能会导致一个TCP包中含有多个消息。
为此有两个解决思路
- 固定消息的长度
- 在消息的边界加入特殊字符
TCP的断网问题
在解决这个问题之前要有三个背景知识
- TCP的重传机制是有限制的,重传到一定次数,os会判定这个tcp链接出现异常,从而关闭这个链接
- TCP的keep-alive机制,这个和http的keep-alive不同,http-keep-alive是长连接保存的时间,tcp-keep-alive是,当tcp两边长时间没有数据交互,就会通过这个机制发送一个报文,保证双方的数据连接没有问题。
- TCP的struct socket结构。这个结构体保存了tcp连接的相关信息,如果tcp连接对应的这个stuct不存在,那么连接也会出问题。(这个和全连接队列中维护的那个不同)
分析:
当某一端的主机崩溃了
- 在双方有数据传送的情况下,有一方主机崩溃了。超过重传次数,都会致使另一端的tcp连接关闭。
- 如果没有数据传送,那么通过keep-alive也可以保证另一端被关闭。
- 如果没有数据传送,也没有打开keep-alive,此时另一端就无法感知主机崩溃,会一直处于establish状态
如果是进程奔溃
进程崩溃,那么内核要回收资源,从而会发送FIN报文,会正常关闭连接
客户机宕机,又快速重启
在有数据传输的情况下,客户机宕机重启后,因为原本的struct结构体不存在了,新发来的报文会回复RST,关闭这个TCP连接
客户机宕机没有重启
出发超时重传到一定次数就会关闭
拔网线
如果拔网线,很快插回去,无论是否有数据传输
- 因为socket这个结构体存在,所以不会影响
如果拔网线,不插回去
会根据是否有数据传输分为:keep-alive和重传保活,如果没有数据传输,且没有开启keep-alive,连接将一直存在。
UDP相关

UDP与TCP对比
- UDP是面向报文的,TCP是面向连接的。
- UDP是不可靠传输,而TCP在 ACK机制、滑动窗口、超时重传机制的帮助下是可靠传输。
- UDP是一对多的协议,而TCP是一对一的协议
- TCP的首部开销比UDP的首部开销大
UDP和TCP的应用场景
- 文件传FTP、HTTPS、HTTP、SSH协议输用的是TCP
- 实时聊天用的是UDP
- DNS解析用的就是UDP、DHCP用的是UDP,这种广播的,同行用UDP
改造UDP使其变得可靠可以从哪个角度考虑
- 还是把这个问题考虑成TCP的可靠传输是如何建立的比较好
HTTP
HTTP报文
请求报文
- 请求行:URI、版本号、请求方法GET POST
- 请求头:USE-ANGENT、Host主机地址等
- 请求体:一些参数
响应报文
- 状态行:
- 响应头:
- 响应体:
HTTP的五个特性
- 简单快速
- 支持服务器/客户端模式
- 无状态
- 无连接
- 灵活
HTTP 和 HTTPS
众所周知HTTP是一个无状态的,明文的协议。
无状态通过Session、Token、Cookie解决了,而明文的问题,就要通过HTTPS解决了。
明文的HTTP,传输的内容很容易就被篡改引发问题。
由此引出了HTTPS

HTTPS增加了SSL/TLS四次握手协议,使其是一个安全的协议。
SSL就是TLS的前世,两者可以等价讨论
SSL/TLS协议的核心要点:
1. 对称加密和非对称加密
2. 摘要算法
3. CA证书权威认证
TLS的四次握手:
- 客户端发送:
- 一个随机数,random-client
- 配套的加密算法
- 支持的TLS版本号
- 服务端接收到,并返回
- 一个随机数,random-server
- 选择的加密算法
- 数字权威证书
- 选择的TLS版本号
- 客户端接收到服务端本次的发送后
- 验证数字权威证书的正确性,如果权威证书是正确的,拿出公钥。
- 生成第三个随机数pre-master,拿公钥加密发送给服务端
- 告知服务端之后的信息都要加密,加密的密钥是三个随机数生成。
- 通过摘要算法把之前的消息打包,然后通过密钥加密发送给服务端
- 验证之前的数据没有被篡改过
- 告诉服务端之后要开始加密传输
- 服务器接受到pre-master,通过私钥解密之后,也会生成一个密钥,并且发送一个加密消息给客户端,表示接下来要加密传送了。
CA证书的颁布过程
5. CA证书通常会包含
1. 公钥
2. 有效时间
3. 颁布者
6 对CA证书中的信息做Hash操作,并且通过私钥加密生成数字签名,并作为数字签名写在文件上
CA证书认证过程
6. 客户端对证书进行Hash(用同样的Hash算法)
7. 通过公钥解密数字签名
8. 对比两个哈希值,判断是否相同
总结一下HTTPS
9. 采用了混合加密,对称加密和非对称加密。对称加密体现在三个随机数生成的密钥,非对称加密体现在第三个随机数时通过公钥加密的
10. 摘要算法 + 数字签名:计算出摘要结果相同,保证内容没有篡改。
11. CA权威认证,保证公钥的正确性。
12. 采用对称加密和非对称加密的好处
1. 采用非对称加密有两个地方
1. 在客户端验证权威证书的时候,会通过公钥解密数字签名。这样保证这个消息来自于服务端
2. 在服务端用私钥解密传递过来的客户端的随机生成的数字pre-master,保证没有明文传输
2. 对称加密性能较高
HTTP 到 HTTP1.1 到HTTP2 到HTTP3
- HTTP3最大特点,采用了UDP代替了TCP
- HTTP1.1:
- 长链接:keep-alive
- 缓存:强制缓存和协商缓存
- 合并小文件请求
- 压缩body部分
- HTTP2:
- 基于HTTPS的
- 头部压缩
- 支持二进制传输
- 多个Stream复用一个TCP连接,完成并发
重定向和请求转发
同
- 两者都是实现跳转的方式
异:
- 请求转发是服务器的行为。客户端发送了一次请求后,虽然发生了跳转,但是都是服务器处理的。
- 重定向是服务器告诉客户端一个新的地址,客户端再一次发送请求。
ARP协议
ARP协议的作用:拿到目标机器的MAC地址。
APR协议的具体流程:
1. 源主机从自身的ARP缓存中,读取对应IP地址的MAC地址
2. 如果没有找到,广播ARP报文,在这个报文中包含 1. 源IP地址与源MAC地址 2. 目标的IP地址。
3. 目标机器收到报文之后,如果目标的IP地址对上,就把自己的MAC地址返回。
4. 双方缓存对方的IP地址与MAC地址
IP相关
IP的首部长度
-
标识:如果一个从传输层传递下来的包,超过MTU的长度会被切分。同一个包切分后由表示标记这个是属于一个包的数据。
-
片偏移:通过片偏移标记自己在包中的位置方便重组
-
标志位:第一位不使用,第二位表示能不能分段,第三位,如果分段了,除了最后一个段,其他的段这个值都设置为1.
-
TTL:一个ip包在网络中最多能跳转的次数
-
首部校验和
-
协议:支持的协议

-
IP地址为什么要分类分类哪些类
- IP地址分类分成了ABCDE五类。其中主要区别就是网络号和主机号的区别。除了DE比较特殊。A类的网络号比较短,主机号比较长,以此类推
- 如果IP地址不分类,那么路由器的路由表会变得非常大,查询也会变得特别慢。因为每一个路由器都要维护所有的ip地址。而分类之后,可以通过网络号区分大概方向,就比较轻松了。
-
路由表中的数据

你就记住路由表中
- Destination:目标地址
- GateWay:网关,下一跳地址
- GenMask:子网掩码
- 一些状态码
-
IPV4 与 IPV6
- 地址长度不同
- 数据包不同
- IPv6可以校验身份比较安全
- DNS记录不同
-
子网掩码的作用
- 区分主机号和网络号
- 划分子网
一个URL键入的过程
按照OSI协议来说或者TCP/IP网络架构来说
- 在应用层,会有这几个协议
- DNS协议,这个协议主要用于解析域名。分为递归过程和迭代过程。递归过程发生在本机访问本地DNS服务器上,迭代发生在本地DNS服务器与根DNS服务器、顶级DNS服务器、权威DNS服务器上,类似于请求转发和重定向的过程。如果有缓存走缓存的。比如浏览器有缓存,本地DNS有缓存都是走缓存的。
- HTTP协议/HTTPS协议:请求报文和响应报文不同
- 在表示层和会话层:按照OSI七层模型来说,SSL/TLS协议应该是在这两层之中的,这两层也主要做一些用户的验证,数据的压缩等等
- 传输层,其实按照TCP/IP模型的话,SSL/TLS其实就是夹在应用层HTTP和传输层TCP之间的。传输层主要是TCP和UDP比较关键。TCP会分装HTTP的消息,并且切分传递给下面的网络层。UDP则是不切分传递给下面的网络层。在传输层,关注的是进程这个层面的通信。
- 网络层,网络层的核心协议是IP协议。协议的首部字段有几个比较关键的。源IP地址、目标IP地址,TTL,协议的版本TCP/UDP,标识,标志位,片偏移。通过把MTU分割上次传递的数据。打包好传递给下方的数据链路层。
- 值得注意的是路由,路由是把网络包分发到目标子网的过程,核心就关注几个点
- 不同子网掩码不要紧,子网是用于划分网络号和主机号的。不管是不是相同的子网掩码,如果最后算出来是一个子网,就是匹配上了,可以把网络包转发过去,如果没有对上说明不是一个子网,不能转发。如果路由表中的所有记录都对不上,那就会转发到默认网关上去。
- 最后找到记录后,路由表记录中,网关地址对应的是空,说明找到对应机器了,如果网关不为空,说明还需要继续转发。
- 路由器和交换器的区别在于:路由器有Mac地址而交换器没有,路由器是三层的而交换器是两层的。
- 路由中的路由表可以通过很多算法来维护,比如是静态路由表就是人工维护,如果是动态的,就有很多算法,比如RIP算法OSFP协议
- 数据链路层,在数据链路层主要就是找到对应的MAC地址。通过ARP去找对应的MAC地址进行真实的发送,在一个IP包传送的过程中,IP地址是不可能发生变化的,但是MAC地址是会发生变化的。
经过以上的传递,服务端也会根据对应的协议解码,最后返回给HTTP响应报文,客户端拿到响应报文进行拆分,再根据body中的数据渲染自己的浏览器,达到访问的效果。
Ping的原理和ICMP
ICMP是什么:ICMP协议主要是确认Ip数据包是否正确的传递到了目的地,并且报告为什么数据包会丢失的原因。
ping就是基于ICMP发送了一个IP包,如果能接收到回应就计算时间,如果接收不到回应就是连接不到,而ping包传递和普通的ip包传递并无太大差别
Tcp/Ip五层模型
- 应用层
- 传输层
- 网络层
- 链路层
- 物理层
HTTP篇
- 常见的状态码
- 1xx:这代表处理中,常见的有100:正在处理
- 2xx:这代表请求被正确的处理了,比如200代表OK,204成功响应,但是没有内容
- 3xx:重定向
- 301代表永久重定向,请求资源不见
- 302临时重定向,资源还在,暂时换个URL访问
- 4xx:客户端的发送问题,所以无法处理,
- 400请求报文有问题
- 404,资源不见了
- 403 无权访问
- 5xx:503:服务器停机了
GET和POST
从语义上讲GET表示从服务器获得指定资源,而POST表示根据请求报文中携带的参数,对指定的资源进行处理。
因此,GET是幂等的安全的,因为他理论上不会对服务器上的资源有什么影响,而POST是不幂等,且不安全的,因为他会修改服务器资源。
GET的参数是明文的,而POST的参数不是明文的,相对来说安全一些
HTTP报文和HTTP头
HTTP报文分为HTTP请求报文和HTTP响应报文

一个HTTP报文通常分为三个部分
:行,请求行和响应行
:头,请求头和响应头
:主体部分
HTTP请求报文
- 请求行:
- 请求的方法。GET/POST/PUT/DELETE/
- URL
- HTTP的版本号:1 - > 1.1 -> 2 -> 3
- 请求头:(只列了一些常见的属性)
- use-agent:浏览器是啥
- Accept:接受的消息的格式 json/xml等等(或许还有Accept-language这样的子弹)
- contentlength:消息长度
- cookie等等
- content-Type:消息的类型
- cache相关的一些字段
- connect:长链接相关字段
- 请求主体:比如Post会放一些参数,get也可以凭借到url后面
HTTP响应报文
- 响应行:URL,状态码
- 响应头:Content-type date
- 响应主题:放置一些内容
HTTP的缓存技术
对于一些重复性的HTTP请求,每次请求得到的数据都是相同的,那么就可以把这些数据都缓存在本地,下次就直接读取本地的数据即可。比如GET就是如此。
- 强制缓存
- 指的是只要浏览器判断缓存没有过期,就直接使用浏览器本地缓存。实现方式是,服务器再返回的请求报文中加入特殊的字段比如Cache-Control或者Expires等字段,设置数据过期的时间,没有过期的数据,就通过浏览器来缓存访问。其中Cache-control的优先级高于Expires
- 协商缓存,协商缓存一定是搭配着强制缓存一起使用的。它有两套机制,分别是
- 请求头中的If-modify-since和响应头中的last-modify通过最近一次修改的时间来比较是否要更新缓存
- 请求头中的If-none-match和响应头中的Etag字段(优先级更高),通过内容来比较
HTTP的演化史
HTTP1.1
- HTTP采用了长链接,来避免创建连接是带来的性能损耗。通过keep-alive来定义连接存活的时间connect字段打开
- HTTP1.1,支持发送多个TCP请求,也就是解决了队头阻塞的问题。因为HTTP,每次发送一个TCP请求后,需要等待响应,才能再发送一个TCP请求。但是还是有响应头阻塞的问题,因为发送数据最后还是要等待服务端响应的
- 压缩资源
- 采用了缓存
HTTP2
- HTTP2是基于HTTPS的,也就是说在TCP和HTTP之间加了一层SSL/TLS协议保证安全性
- HTTP2会压缩HTTP报文的重复头部内容
- HTTP2采用二进制传输(整体),性能比较高
- 采用了Stream流。什么是Stream流
一个Stream可以包含多个Message,一个Message可以包含多个Frame
HTTP3
HTTP3面临的问题。随着时代进步,手机的普及,我们知道一个TCP连接的标识符是目标ip目标端口,源端口和源ip。
如果切换网络,源ip变化,就要重新创建连接,就比较耗时。因此HTTP3大胆的使用了一个在应用层的QUIC协议,底层是一个UDP协议
QUIC通过ConnectId,重连消耗比较少
QUIC主要通过超时重发ACK来保证数据的可靠性