计算机网络的高频20点
计算机网络相关概念
TCP连接
用于保证可靠性和流量控制维护的某些状态信息,这些信息的组合,包括 Socket、序列号和窗口大小称为连接。

唯一确定一个连接
通过一个四元组来确定一个连接:

TCP头部信息

- 序列号:用来解决网络包乱序的问题。
- 确认应答号:解决丢包的问题。
- 控制位:
1)ACK:确认应答给对端的消息,除了第一个syn包,其他的包都需要带上这个标志位。
2)RST:表示断开连接,并且是强制断开。
3)SYN:表示希望建立连接;
4)FIN:表示不会发送消息,希望断开连接。
TCP和UDP的特点
- TCP面向连接,但是UDP不需要。
- TCP为一对一连接,但是UDP不是,可以一对一,也可以一对多。
- 可靠性,TCP是可靠的,无差错,不重复,不丢失、不乱序。
- TCP拥有拥塞控制,流量控制。
- TCP会协商MSS进行分片大小,UDP不会,是直接在IP层分片。
MTU与MSS
- MTU:一个网络包的最大长度,以太网是1500字节,
- MSS:一个网络包中的TCP数据包的大小,比较极限的情况下:
MSS + IP头部长度 + TCP头部长度 = MTU
TCP三次握手

连接的过程与状态转移
- 第一个包是
syn包,表示client想要建立连接。(client发送后处于syn_sent状态) - 第二个包是
syn + ack包,表示server想要建立连接并且回答client的消息。(server接收syn包,并发送syn+ack包后到处于syn_recv状态) - 单纯的
ack包,可以携带数据,表示client收到确定建立连接的消息。(client接受syn+ack包,发送ack包之后处于established状态)
为什么是三次握手,而不是两次或者四次
如果是两次握手造成历史连接,不能同步序列号,已建立连接需要断开资源浪费

会为了在两次握手的情况下,服务端没有中间状态给客户端来阻止历史连接,导致服务端可能建立一个历史连接,造成资源浪费。
如果是四次握手避免过多的通信次数
四次握手说白了就是把中间的syn+ack包分成两个包,一个syn,一个ack,但是这样的话会导致过多的通信次数。
为什么每次建立TCP连接的时候需要保证初始化序列号不一样呢?怎么保证的呢?
为了保证历史连接被下一个四元组接受

为了通信安全,防止黑客伪造的相同序列号的 TCP 报文被对方接收- 初始序列号
ISN的产生:ISN = M + F,M为一个计时器,F为根据四元组算出来的哈希值(通常采用MD5),(时间不同,四元组不同即可唯一确定一个ISN)
MTU和MSS的作用
如果TCP数据包交给IP分片(根据MTU分片),那么出现一个IP分片丢失的情况下,整个TCP包都需要重新发送,因为IP没有组建TCP包的能力,如果根据TCP分包(根据MSS),则丢失哪个发送哪个就行了。
TCP握手期间丢包会发生什么
丢失第一个包syn包
- client:会觉得server没有收到这个syn包,所以会触发超时重传(
超时重传的序列号是一样的),超时重传的时间是会翻倍的,如重传时间为1s,重传次数是5次,那么整个时间会是1 + 2 + 4 + 8 + 16 + 32 = 63s,大概一分钟,则client会断开连接。 - server:没反应,因为至始至终都没有消息。
丢失第二个包syn+ack包
- client:会觉得server没有收到第一个包,会发生丢失第一个包syn时候同样的事情,超时重传(
序列号是一样的)。 - server:会觉得clinet没有收到这个包,服务端这边会触发超时重传机制,重传 SYN-ACK 报文(
序列号是一样的)。
虽然都发生了重发,但是client和server都是按照自己的接收的序列号来确定该不该接受该包
丢失第三个包ack包(ack包不会单独重发)
- client:默认server收到了ack消息,开始进行通信(client会认为三次握手已经完成,开始通信了)。
- server:会认为client没有收到第二个包,出发超时重传。
半连接(syn队列)、全连接队列(accept队列)与syn攻击的解决方案

syn攻击
攻击者短时间伪造不同 IP 地址的 SYN 报文,服务端每接收到一个 SYN 报文,就进入SYN_RCVD 状态,但服务端发送出去的 ACK + SYN 报文,无法得到未知 IP 主机的 ACK 应答,久而久之就会占满服务端的半连接队列,使得服务端不能为正常用户服务。(也就是说多个连接client发送syn包之后不予理会server,不能收到clinet的ack包,就一直占用syn队列)
syn解决方案
网卡与服务器之间的有个队列保存这些连接,调大这个队列的大小。增大TCP半连接队列的大小。- 使用
syncookie绕过半连接队列,server直接根据算法算出一个cookie值发给client,然后server收到client回复的ack之后验证这个ack的合法性,然后直接进入accept队列。 减少syn+ack的重传次数,目的是让server尽快的断开连接,使得这个连接移除出半连接队列中。
TCP四次挥手
发送fin包的前提是关闭写数据才能触发

- 第一个包是
fin包:client端没有需要发送的数据了(关闭了写端),这个时候就要发送FIN包。(client发送完就变成fin_wait1状态) - 第二个包是
ack包:server回复client发送的fin包。(server接收到fin包回复ack包之后变成close_wait状态) - 第三个包是
fin包,server发送的包,表示服务器已经将要发的消息发送完,要断开连接。(client收到该消息回复ack变成last_ack状态) - 第四个包是
ack包,回复server的fin消息。(client回复server的消息之后状态更新为time_wait的状态,server收到ack包之后变成close状态) - 此后,client端会在time_wait状态停留2MSL(报文存活的时间),确保本次通信的所有包都失效后,变为
close状态。
为什么需要4次挥手,不能和握手一样变成3次吗?
原因一:
由于断开连接是由一方比如client主动发出的,所以server收到消息之后不能确定自己的消息已经发送完成,所以还需要最后将自己的消息发送完整之后断开连接。所以在回复client端之后还需要将没有发送完成的消息发送完之后,server发送fin包。
原因二:
有的情况会变成三次,如当server端没有数据发送,并且TCP开启了延迟确定的机制,那么第二次和第三次挥手会合并在一起发送过去。
TCP延迟确定机制
为了解决TCP的ack包不携带数据的问题,十分浪费,所以延迟确定机制是看一定时间内是不是有数据发送,有的话和第二次的单纯ack包一起发送,没有的话会将server的fin包作为数据一起发送过去-------》四次就变成三次了。
四次挥手丢包会发生什么?
丢失第一个包fin包
- client: 触发超时重传机制,如果超时的话就直接从fin_wait1直接变成close状态。
- server:没有什么反应。
丢失第二个包ack包
- client: 注意单纯的ack包是不会重传的,client会不断发送fin包,触发超时重传。
- server:一旦收到client的重传的fin包之后就发送一次ack,直到client收到ack包。

丢失第三个包fin包(有点特殊,还是一个等待server消息的状态)
- client:如果是close关闭的,那么在等待一个默认的时间之后会直接关闭连接,如果是shutdown关闭的会死等,等待server的消息。
- server:触发超时重传
丢失第四个包ack包
- client:ack包不会重新发送,server会触发超时重传,那么client收到一次重传消息就发送一次发送一次ack包;
- server:触发超时重传。
为什么说close是暴力的关闭,shutdown关闭的作用

为什么time_wait状态为2MSL
MSL为报文存在的最长时间,超过这个时间之后报文就会销毁,设置为2MSL是为了本四元组的通信的消息全部销毁,不会被下一个四元组接受。
如果服务端出现大量的time_wait状态为什么?怎么解决?
注意,之后主动断开的一方有time_wait状态
为什么会出现大量的time_wait状态?
- 大量的短连接并且是server主动断开的连接
- 大量的长连接超时。
- 连接数量已经达到server的最大连接数量
解决方案
- 将短连接变成长连接,比如http的长连接键值对:connect:keep-alive
- 如果是大量的长连接超时,那么大概率是网络问题。
- 调大该参数即可
服务端出现大量的close_wait状态
说明client出动断开的连接,server卡在close_wait的原因是没有调用close函数关闭连接
- 没有调用accept函数接受新的连接。
- server的lfd没有注册epoll,没有上树。
- 新的连接fd进来没有注册epoll,没有上树。
- 在调用close之前出现异常,导致没有调用到close。
TCP的重传
超时重传
以时间为基础,要是超时重传时间RTO >= RTT(一个数据发送出去到接收到回信的时间差),触发超时重传,超时重传的时间会翻倍,每超时一次时间都是翻倍的。
快速重传
以接受对端的数据为主,一个丢失的包的收到三次就会触发快速重传。
SACK方法
它可以将已收到的数据的信息发送给「发送方」,这样发送方就可以知道哪些数据收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据。
TCP的滑动窗口、流量控制
滑动窗口
为了解决单一报文响应时间过长的原因,根据双方的接受能力,设置window窗口的大小,TCP滑动窗口的大小是接受缓冲区有一定的关系。
流量控制
根据双方的实际的接受能力来决定发送窗口的大小,即流量控制
- 接受和发送窗口的大小和什么有关
1)与接收缓冲区有很大的关系,接收缓冲区直接决定发送窗口的大小。
- 与
应用层读取的数据有关,读取的数据可以释放缓冲区占用的数据。
- 窗口关闭
当接收窗口变为0的时候,对端将无法发送数据,对端将会死等在那里,会采用窗口探测来解决。窗口探测的次数一般为3 次,每次大约 30-60 秒(不同的实现可能会不一样)。如果 3 次过后接收窗口还是 0 的话,有的 TCP 实现就会发RST 报文来中断连接。
TCP的拥塞控制
为什么需要拥塞控制?
流量控制是为了了解对端的接收能力,从而控制流量控制发送窗口的大小,但是拥塞控制是为了了解网络的拥塞程度的,如果没有拥塞控制的话,那么如果网络拥塞,导致超时重传的话会导致报文不断重复发送,那么网络将会变得更加拥塞,那么就会进入一个矛盾的死局中。
慢启动、拥塞避免、拥塞发生、快速回复算法的关系
首先按照慢启动算法启动,然后到达慢启动门限ssthresh后,启动拥塞避免算法,之后发生拥塞之后看重传采用的是什么算法,如果是超时重传的话那就是拥塞发生算法,如果是快速重传,那就是采用快速回复算法。
慢启动算法
在达到慢启动门限之前按照每一轮(一来一回一个完整的通信过程)的翻倍去决定拥塞窗口的大小。
拥塞避免算法
表示到达慢启动门限之后按照轮次线性增加拥塞窗口的大小。
拥塞发生之后采用的算法
1.超时重传
如果是超时重传的话,那么采用的就是拥塞发生算法,该算法的描述为:
1)慢启动门限(ssthresh)设为现在的窗口大小(cwnd)/2。
2)cwnd重置为初始值,如果初始值是1,那么就是恢复的1。
缺点:过度保守或过度激进,导致网络资源未能充分利用,过度的变化率太大可能会导致网络拥塞加剧或者丢包率增加。

2. 快速重传
如果是快速重传的话,那么采用的就是快速恢复算法,该算法的描述为:
1)ssthresh = cwnd/2,也就是原来的一半;
2)cwnd = cwnd/2,也就是设置为原来的一半;
3)进入快速恢复算法;

快速恢复算法的解释: 在刚开始出现网络拥塞的时候,采用门限减半(和原来的是一样的)、窗口大小变为ssthresh+3。快速重传和快速恢复算法一般同时使用,快速恢复算法是认为,你还能收到 3 个重复 ACK 说明网络也不那么糟糕,所以没有必要像 RTO 超时那么强烈。
cookie、session和token
cookie、session和token的作用
HTTP作为无状态协议,必然需要在某种方式保持连接状态。那么cookie诞生了,就是为了保存当前连接的一个状态。
- 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
- 个性化设置(如用户自定义设置、主题等)
- 浏览器行为跟踪(如跟踪分析用户行为等)
session 和 token 本质上是没有区别的,都是对用户身份的认证机制,只是认证的机制不一样,然后cookie是存在client端的
Cookie
Cookie是客户端保持状态的方法, Cookie简单的理解就是存储由服务器发至客户端并由客户端保存的一段字符串。为了保持会话,服务器可以在响应客户端请求时将Cookie字符串放在Set-Cookie下,客户机收到Cookie之后保存这段字符串,之后再请求时候带上Cookie就可以被识别。
除了上面提到的这些,Cookie在客户端的保存形式可以有两种,一种是会话Cookie一种是持久Cookie,会话Cookie就是将服务器返回的Cookie字符串保持在内存中,关闭浏览器之后自动销毁,持久Cookie则是存储在客户端磁盘上,其有效时间在服务器响应头中被指定,在有效期内,客户端再次请求服务器时都可以直接从本地取出。需要说明的是,存储在磁盘中的Cookie是可以被多个浏览器代理所共享的。
Session
Session是服务器保持状态的方法。
首先需要明确的是,Session保存在服务器上,可以保存在数据库、文件或内存中,每个用户有独立的Session用户在客户端上记录用户的操作。我们可以理解为每个用户有一个独一无二的Session iD作为session文件的Hash键,通过这个值可以锁定具体的session结构的数据,这个Session结构中存储了用户操作行为。
当服务器需要识别客户端时就需要结合Cookie了。每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用Cookie来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端需要在Cookie里面记录一个SessionID,以后每次请求把这个会话!D发送到服务器,我就知道你是谁了。
token(和session功能相似)
Token 是一种在客户端和服务器之间传递身份验证和授权信息的方式。它通常是一个加密的字符串,服务器生成并发送给客户端,客户端将其存储起来,并在每次请求时将其发送回服务器。常见的类型包括 JWT (JSON Web Token)。
GET和POST方法
安全和幂等
- 安全:在 HTTP 协议里,所谓的「安全」是指请求方法不会「破坏」服务器上的资源。
- 幂等:所谓的「幂等」,意思是多次执行相同的操作,结果都是「相同」的。
GET方法
GET 方法就是安全且幂等的,因为它是「只读」操作,无论操作多少次,服务器上的数据都是安全的,且每次的结果都是相同的。所以,可以对 GET 请求的数据做缓存,这个缓存可以做到浏览器本身上(彻底避免浏览器发请求),也可以做到代理上(如nginx),而且在浏览器中 GET 请求可以保存为书签。
POST方法
POST 因为是「新增或提交数据」的操作,会修改服务器上的资源,所以是不安全的,且多次提交数据就会创建多个资源,所以不是幂等的。所以,浏览器一般不会缓存 POST 请求,也不能把 POST 请求保存为书签。
加密安全
两者的URL虽然一个在请求行,一个在请求体中,但是两者都是不安全的,因为即使POST请求是在体中,但是抓包之后依然是可以看到完整的内容的,所以,http没有加ssl的安全人证之前都是不安全的,和请求方法无关
HTTP的常见状态码和字段
常见的状态码

具体几个常考的状态码
- 200,是最常见的
成功状态码,表示一切正常。 - 301,表示
永久重定向,需要改用新的URL才能访问到。 - 302,表示
临时重定向,表示需要用临时的URL才能访问。 - 404,表示该资源不存在,客户端访问量不存在的资源。
常见的字段
- HOST:对应服务端的域名
- Connect-Length:表示数据的长度。
- Connection:表示连接是
长类型还是短类型。 - Content-Type:表示数据的格式是什么,比如是text/html; Charset=utf-8。
- Content-Encoding:表示的是采用什么压缩方式。
HTTP和HTTPS
HTTP1.1的优点
简单
HTTP的报文格式是header+body的形式给出的,所以易于理解,信息也是根据key-value来给出的。灵活易于拓展
HTTP 协议里的各类请求方法、URI/URL、状态码、头字段等每个组成要求都没有被固定死,都允许开发人员自定义和扩充。应用广泛,并且支持跨平台
HTTP1.1的缺点
无状态的双刃剑
1)无状态的好处,因为服务器不会去记忆 HTTP 的状态,所以不需要额外的资源来记录状态信息,这能减轻服务器的负担。
2)无状态的坏处,无状态的坏处,既然服务器没有记忆能力,它在完成有关联性的操作时会非常麻烦。例如登录->添加购物车->下单->结算->支付,这系列操作都要知道用户的身份才行。明文传输的双刃剑
1)明文意味着在传输过程中的信息,是可方便阅读的,比如 Wireshark 抓包都可以直接肉眼查看,为我们调试工作带了极大的便利性。
2)但是这正是这样,HTTP 的所有信息都暴露在了光天化日下,相当于信息裸奔。在传输的漫长的过程中,信息的内容都毫无隐私可言,很容易就能被窃取,如果里面有你的账号密码信息,那你号没了。安全性问题(可以和2一起记)
由于http是明文传输的,所以传输的内容很容易被人:
1)被窃听
2)被篡改
3)被伪装
HTTP1.1的性能相比1.0的优点
长连接
早期 HTTP/1.0 性能上的一个很大的问题,那就是每发起一个请求,都要新建一次 TCP 连接(三次握手),而且是串行请求,做了无谓的 TCP 连接建立和断开,增加了通信开销。
为了解决上述 TCP 连接问题,HTTP/1.1 提出了长连接的通信方式,也叫持久连接。这种方式的好处在于减少了 TCP 连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。解决对头阻塞的问题
HTTP/1.1 管道解决了请求的队头阻塞,但是没有解决响应的队头阻塞,也就是可以同时发送多个http请求。
HTTPS
- HTTPS解决了哪些问题
为了解决HTTP的明文传输导致的安全问题,从而进行HTTP+SSL的安全认证过程。
1)窃听风险
混合加密的方式实现信息的机密性,解决了窃听的风险。

HTTPS 采用的是对称加密和非对称加密结合的「混合加密」方式:
在通信建立前采用非对称加密的方式,即公钥和私钥的方式。
在通信过程中全部使用对称加密的「会话秘钥」的方式加密明文数据。
篡改风险
摘要算法的方式来实现完整性,它能够为数据生成独一无二的「指纹」,指纹用于校验数据的完整性,解决了篡改的风险。

用摘要算法(哈希函数)来计算出内容的哈希值,也就是内容的「指纹」,这个哈希值是唯一的,且无法通过哈希值推导出内容。冒充风险
将服务器公钥放入到数字证书中,解决了冒充的风险。

- TLS/SSL握手(RSA算法,即指数取余算法)的过程

1)客户端产生一个随机数a,发给服务端。
2)服务端产生一个随机数b,发给客户端。
3)服务端将服务器的数字证书发给客户端。
4)客户端验证服务端发送的数字证书。
5)验证成功并且取出公钥。
6)公钥加密一个随机数c,发送给服务端。
7)服务端根据密钥解密出c。
至此,客户端和服务端都是具备a,b,c三个数的,根据这三个数用RSA算法,两者得到会话密钥,然后用会话密钥加密通信
缺点:使用 RSA 密钥协商算法的最大问题是不支持前向保密(也就是一旦服务端的密钥泄露,那么前面截取到的信息都会被解密)。因为客户端传递随机数(用于生成对称加密密钥的条件之一)给服务端时使用的是公钥加密的,服务端收到后,会用私钥解密得到随机数。所以一旦服务端的私钥泄漏了,过去被第三方截获的所有 TLS 通讯密文都会被破解。
正是基于此,所以需要一个新的算法来解决这个问题
3. TLS/SSL握手(ECDHE算法,即指数椭圆线点取余算法)的过程
https://blog.csdn.net/mrpre/article/details/78025940
ESA与ECDHGE区别:
- RSA 密钥协商算法「不支持」前向保密,ECDHE 密钥协商算法「支持」前向保密;
- RSA的会话密钥,就是用
客户端随机数a + 服务端随机数b + 公钥加密的c 」三个材料生成的,不具有前向保密性,ECDHE就是用客户端随机数a + 服务端随机数b + c(ECDHE 算法算出的共享密钥) 」三个材料生成的,这是因为每个会话使用的密钥对是临时生成的,不会长期存储或重复使用,具备前向保密性。 - ECDHE算法在发送完证书后会发送一个「Server Key Exchange」消息,而RSA没有。
IP相关知识
IP地址分类

分类的缺点:
- 灵活性不够高,已经定死的分类
- 类别的主机太少了,C类地址甚至连一个网吧都不够用
CIDR无分类地址
为了解决分类的缺点,采用特定的方法来分类IP地址
- 网络号+主机号
表示形式 a.b.c.d/x,其中 /x 表示前 x 位属于网络号, x 的范围是 0 ~ 32,这就使得 IP 地址更加具有灵活性。
比如 10.100.122.2/24,这种地址表示形式就是 CIDR,/24 表示前 24 位是网络号,剩余的 8 位是主机号。 - IP地址+子网掩码

公有IP和私有IP

在每一个IP类别上都有一个对应的私有IP的地址。
IP分片与重组
- IP分片
每种数据链路的 MTU 之所以不同,是因为每个不同类型的数据链路的使用目的不同。使用目的不同,可承载的 MTU 也就不同。
其中,我们最常见数据链路是以太网,它的 MTU 是 1500 字节。
那么当IP 数据包大小大于 MTU 时, IP 数据包就会被分片。 - IP重组
经过分片之后的 IP 数据报在被重组的时候,只能由目标主机进行,路由器是不会进行重组的,目标主机根据偏移量进行IP重组

IP相关的协议技术
- DNS(域名解析):域名->IP地址
是一个存储域名与IP对应关系的分布式服务器,但是只是指路,不带路


域名解析的过程(指路的过程)
发送一个DNS请求->浏览器缓存->本地DNS服务器(也就是本地客户端绑定的DNS服务器)->根域(根目录,他会给你一个顶级域名的地址)->.com或者.n的顶级域名服务器(他会给你一个权威域名服务器的地址)->得到想要的答案
ARP(由IP得到下一跳的MAC地址)

采用广播的形式向所有同一个链路的所有路由器发送一个UDP报文,如果是自己的地址,设备就将自己的 MAC 地址塞入 ARP 响应包返回给主机
RARP(由MAC地址得到IP地址)
ARP 协议是已知 IP 地址求 MAC 地址,那 RARP 协议正好相反,它是已知 MAC 地址求 IP 地址。例如将打印机服务器等小型嵌入式设备接入到网络时就经常会用得到。
通常这需要架设一台 RARP 服务器,在这个服务器上注册设备的 MAC 地址及其 IP 地址。然后再将这个设备接入到网络。

DHCP(动态配置IP地址的服务器)

全程都是使用UDP广播通信
ICMP(控制报文协议)
- ICMP 主要的功能包括:
1)确认 IP 包是否成功送达目标地址
2)报告发送过程中 IP 包被废弃的原因
3)改善网络设置等 - 分类:
1)一类是用于诊断的查询消息,也就是「查询报文类型」
2)一类是通知出错原因的错误消息,也就是「差错报文类型」
组播(多播)、广播、单播


浙公网安备 33010602011771号