DNS解析
DNS------Domain Name System,域名系统,将主机名改为IP地址
chrome://net-internals/#dns 可以查询某个域名下的DNS缓存 04 DNS解析流程 - 掘金
DNS解析的两种方式
- 递归查询
在该模式下DNS服务器接收到客户机请求,必须使用一个准确的查询结果回复客户机。如果DNS 服务器本地没有存储查询DNS 信息,那么该服务器会询问其他服务器,并将返回的查询结果提交给客户机。
- 迭代查询
DNS服务器会向其他客户机提供其他能够解析查询请求的DNS服务器地址,当客户及发送查询请求时,DNS 服务器并不直接回复查询结果,而是告诉客户机另一台DNS 服务器地址,客户机再向这台DNS 服务器提交请求,依次循环直到返回查询的结果
HTTP缓存
- Expires:响应头,代表该资源过期时间。如果客户端与服务端时间因为某些原因(时区不同;客户端或者服务端一方时间不准确)发生误差,结果不如意,设置max-age时expires不生效
- Cache-Control:控制缓存行为
HTTP1.1中Cache-Control已经被expires替换
- no-cache:防止从缓存返回过期资源。如果客户端发请求中包含该指令,则客户端不会接收缓存过的响应。如果服务端返回响应中包含该指令,则源服务器不再对缓存服务器请求资源有效性进行确认,且禁止对响应资源进行缓存。
客户端缓存内容,是否使用缓存需要协商缓存验证决定
- no-store:暗示请求或响应包含机密的响应,表示缓存在本地不能存储请求或相应的任一部分
- max-age:一个时间长度,在时间长度内有效
- Last-Modified:浏览器向服务端发起请求后服务器放在响应头返回的文件最后更改时间
- If-modified-since:被保存的last-modified的值,会在浏览器协商缓存时发送到服务器。服务器通过读取这个字段并与文件最后的更改时间做比较,相同则返回空,不同则将更新后文件与文件最新更新时间返回至浏览器
- E-tag:告知客户端实体标识。服务器会为每份资源分配对应的Etag值
- If-none-match:用于指定该字段的实体标记,与请求资源的Etag不一致时,告知服务器处理该请求
OSI网络模型
TCP/IP网络模型
- 应用层:为用户提供功能。FTP(文件传输协议),DNS,HTTP。
处理报文,请求解析参数,请求hash值,请求域名,请求头
- 传输层:为用户层提供网络支持。TCP(传输控制协议),UDP(用户数据报协议)。
- 建立端口到端口的关系,会携带端口号。端口号是用来区分正在接收或传输数据的不同应用
- 应用层需要传输的数据可能非常大,如果直接传输不好控制,如果当传输层的数据包大小超过MSS(TCP最大报文段长度),就要将数据包分块成为一个TCP段
- 网络层:规定了通过怎样的路径到达对方计算机,并将数据包传给对方。网络层负责将数据从一个设备传输到另一个设备。IP(互联网协议),ARP(地址解析协议,根据IP获取物理地址)
- IP会将传输层的报文作为数据部分加上IP包头组成IP报文,如IP报文超过MTU(最大传输单元,以太网中一般为1500字节),就会再次进行分片,得到IP报文
- IP地址分为网络号和主机号。网络号负责标识该IP地址属于哪个子网,主机号负责表示同一子网下不同主机
- IPV4:点分十进制表示,32位,4段。eg:192.168.254.1
- IPV6:冒号分隔16进制,128位。eg:0123:4567:89ab:cdef:0123:4567:89ab:cdef
- 数据链路层:传输层的报文段转移给物理层。这个设备一般是路由器、
每一台设备的网卡都会有一个MAC地址,他就是用来标识唯一设备的。路由器计算出了下一个目的地IP地址,再通过ARP协议找到该目的地的IP地址,这样就知道这个IP是哪个设备的了
HTTP
HTTP:超文本传输协议。是一个在计算机世界里专门在两点之间传输文字,图片,音频,视频等超文本数据的约定和规范,是双向的。
状态码
1xx:提示信息,表示目前是协议处理的中间状态,还需要后续的操作(用的比较少)
- 100 Continue:客户端应继续请求
- 101:切换请求协议,服务器根据客户端请求切换更高的协议从http=>websocket。协议升级机制
2xx:成功,报文已经被收到且正确处理
- 200:请求成功,有响应体。非HEAD请求,服务器的响应头都会有body数据
- 201:请求成功,创建新的资源,使用场景是作为 POST 请求的返回值
- 204:报文中不含实体的主体部分,响应头没有body数据
- 206:范围请求,返回范围内容
3xx:重定向,资源位置发生变动,需要客户端重新发送请求
- 301:永久性重定向,请求的资源已经不在了,需使用新的URL进行访问。需要用Location字段表示新的URL
- 302:临时重定向,请求的资源还在,但暂时需要用另一个URL访问。需要用Location字段表示新的URL
- 303:应使用get请求资源对应的url
- 304:协商缓存命中,不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,用于缓存控制
- 307:临时,不会将post改为get
4xx:客户端错误,请求报文有误,服务器无法处理
- 400:客户端请求报文有误
- 403:服务端禁止访问资源
- 404:请求资源在服务器不存在或没找到
5xx:服务器错误,服务器在处理请求时内部发生了错误
http常见请求方式
HTTP1.0定义了:
- get:获取数据,请求访问已被URl识别的资源
- post:提交数据,传输实体主体
- head:获得报文首部,不返回报文主体部分,用于确认url的有效性和资源更新的日期时间
HTTP1.1新增:
- options:询问支持方法,用来查询针对请求url指定的资源支持的方法
- put:传输文件,由于HTTP1.1的put方法不带验证机制,所以一般不适用
- delete:删除文件,由于HTTP1.1的delete方法不带验证机制,所以一般不适用
- trace:追踪路径让web服务器端将之前的请求通信返回的客户端
- connect:要求用隧道链路代理,主要用ssl将同性能内容通过网络隧道传输
- patch:用于对资源进行部分修改
get与post的区别
- get方法的含义是请求从服务器获取资源,post是发送数据给服务器(新增或提交数据的操作)
- get通过地址栏传输,post通过报文传输
- get参数有长度限制,post没有
- get只支持ASCII字符,post支持标准字符集
- get是幂等的,post是不平等的
- get产生一个tcp包,post产生两个tcp包。get会将请求和请求数据一起发过去,post会先打个招呼,响应100后再发送数据包
安全:在HTTP协议里,所谓的安全是指请求方法不会破坏服务器上的资源
- GET
- HEAD
- OPTIONS
幂等:多次执行相同的操作,结果都是相同的
- GET
- PUT
- HEAD
- OPTIONS
- DELETE
http常见字段
- Host:客户端发送请求时,用来指定服务器的域名
- Content-Length:服务器在返回数据时,会有content-length,表示本次回应的数据长度
- Connection:常用于客户端要求服务器使用TCP持久连接,以便其他请求复用
HTTP/1.1版本的默认链接都是持久连接,但是为了兼容老版本的HTTP,需要指定Connection首部字段为Keep-Alive
- Content-Type:用于服务器回应时,告诉客户端,本次数据是什么格式
- Accept:客户端在请求时表明自己可以接受哪些数据格式
- Content-Encoding:说明数据的压缩方法,表明服务器返回的数据使用了什么压缩格式
- Accept-Encoding:客户端 在请求时说明自己可以接受那些压缩方法
HTTP特点
- 简单:报文格式header+body,头部信息也是key-value
- 灵活,易于扩展:请求方法,url,状态码,头字段等每个要求都没有固定死,允许自定义和扩充,http应用在OSI第七层,下层可随意变化
- 应用广泛,跨平台
缺点:
- 无状态:不需要额外的资源来记录状态信息,减轻服务器的负担。但是完成关联操作比较麻烦,比如登录,添加购物车,下单,结算,支付等需要身份信息,可以用cookie解决
- 明文传输
- 不安全:
HTTPS
- 混合加密------机密性
- 在通信建立前采用非对称加密的方式交换密钥,后续就不再使用非对称加密
- 在通信过程中全部使用对称加密的会话密钥的方式加密明文数据
使用混合加密的原因
- 对称加密只使用一个密钥,运算速度快,密钥必须保密,无法做到安全的密钥交换
- 非对称加密使用两个密钥,公钥和私钥,公钥可以任意分发而私钥保密,解决了密钥交换问题但是速度慢
- 摘要算法:为数据生成独一无二的指纹,用于校验数据完整性
客户端在发送明文之前会通过摘要算法算出明文的指纹,发送的时候讲指纹和明文一同加密成密文后,发送给服务器,服务器解密后,用相同的摘要算法算出发送过来的明文,通过比较客户端携带的指纹和当前算出的指纹做比较,若指纹相同,则说明数据是完整的
- 数字证书
服务器将自己的公钥注册到CA(数字证书认证机构),CA用自己的私钥将服务器的公钥数字签名并颁发数字证书,客户端拿到服务器的数字证书后,使用CA的公钥确认服务器的数字证书的真实性,从数字证书获取服务器公钥后,使用它对报文加密后发送,服务器用私钥对报文进行解密
SSL/TLS协议基本流程
SSL中文叫作安全套接层,TLS中文叫作传输层安全协议,是IETF将SSL标准化后的名称,两者是同一个东西的不同阶段
- 客户端向服务器索要并验证服务器的公钥
- 双方产生会话密钥
- 双方采用会话密钥进行加密通信
SSL/TLS涉及的四次通信建立的详细流程:
- Client Hello
客户端向服务器发起加密通信请求,也就是ClientHello请求。客户端向服务器发送以下信息:
- 客户端支持的SSL/TLS协议版本
- 客户端生产的随机数,后面用于生产会话密钥
- 客户端支持的密码套件列表,如RSA加密算法
- Server Hello
服务器收到客户端请求后,向客户端发出响应,也就是serverHello,服务器回应以下内容:
- 确认SSL/TLS版本,如果浏览器不支持,则关闭加密通信
- 服务器生产的随机数,用于后面生产会话密钥
- 确认的密码套件列表,如RSA加密算法
- 服务器的数字证书
- 客户端回应
客户端收到服务器的回应之后,首先通过浏览器或操作系统中的CA公钥,确认服务器数字证书的真实性。如果证书没有问题,客户端会从数字证书中取出服务器的公钥,然后用它使用加密报文,向服务器发送以下信息:
- 一个随机数,该随机数会被服务器公钥加密
- 加密通信算法改变通知,表示随后的信息都将用会话密钥加密通信
- 客户端握手结束通知,表示客户端的握手阶段已经结束,这一项同时将之前所有内容发生的数据做个摘要用于服务端校验
- 服务器的最后回应
服务器收到客户端的第三个随机数之后,通过协商的加密算法,计算出本次通信的会话密钥,然后向客户端发送最后的信息:
HTTP和HTTPS对比
- HTTPS协议需要将CA(证书权威机构)申请数字证书,来保证服务器身份可信
- HTTP端口号为80,HTTPS为443
- HTTP链接建立相对简单,TCP三次握手之后便可以进行传输;HTTPS在三次握手之后还需要进行SSL握手过程才可以进行加密传输
- HTTP是明文传输,HTTPS在HTTP和TCP之间加入SSL安全协议
HTTP演进
HTTP1.1如何优化?
- 如何避免发送HTTP请求?
使用缓存技术。客户端将第一次请求以及响应的数据保存在本地磁盘上,将请求的URL作为key,而相应作为value,两者为映射关系
服务器在发送响应时,会估算一个过期时间,并将其放在响应头中,一旦客户端发现缓存过期就会重新发送网络请求。客户端会在重新发送请求时在Etag头部带上第一次请求的响应头部中的摘要
- 如何减少HTTP请求次数?
- 减少重定向次数:将重定向的工作交由代理服务器完成
- 合并请求
- 将多个访问小文件的请求合并成一个大的请求。
- 将小图片合成大图片的方式
- 服务端使用webpack等打包工具将js,css等资源合并打包成大文件
- 将图片的二进制数据用base64编码后,以url的形式潜入到HTML文件,跟随HTML文件一起发送
- 将多个访问小文件的请求合并成一个大的请求。
弊端:当大资源中的某个小资源发生变化后,客户端需要重新下载整个完整的大资源文件
- 延迟发送请求:按需获取
- 如何减少HTTP响应的数据大小?
对响应的资源进行压缩
- 无损压缩:资源经过压缩后,信息不被损坏,还能恢复到压缩前的原样,适用于在文本文件,程序可执行文件,程序源代码。gzip,Brotli
无损压缩需要对原始资源建立统计模型,利用这个统计模型将常出现的数据用较短的二进制比特序列表示,将不常出现的数据用较长的二进制比特序列表示,生成二进制比特序列一般是霍夫曼编码算法
客户端通过请求头的Accept-Encoding字段告诉服务器支持的压缩算法
服务器会从支持的或者合适的压缩算法中选择一个,然后对响应资源进行压缩,最后通过响应头部中的Content-Encoding字段告诉该资源使用的压缩算法
- 有损压缩:解压的数据会与原始数据不同但是会非常接近。
会将次要的数据舍弃,牺牲一些质量来减少数据量,提高压缩比,经常用于压缩多媒体数据。
通过HTTP请求头中Accept字段里的q质量银子高速服务器期望的资源质量
HTTPS怎样优化?
- 分析性能损耗
- TLS协议握手过程
- 握手过程中客和服都需要临时生成椭圆曲线公私钥
- 客户端验证证书时,会验证是否被吊销
- 双方计算对称加密秘钥
- 握手后的对称加密报文传输,这个环节的性能损耗比较小
- 硬件优化
HTTPS协议是计算密集型不是IO密集型,所以一个好的CPU可以提高计算性能
- 软件优化
- 软件升级:将正在使用的软件升级到最新版本,最新版本不仅提供了最新的特性还优化了以前软件的问题或性能
- 协议优化:对密钥交换过程的优化(改动比较小)
- 证书优化
- 证书传输
- 证书验证
- 会话复用
- session ID
客户端和服务器首次TLS握手连接后,双方会在内存缓存会话密钥,并用唯一的Session ID来表示。当客户端再次连接时,消息中会带上session ID,服务器收到后就会从内存找,如果找到就直接用该会话密钥恢复会话状态,跳过其余的过程,只用一个消息往返就会建立安全通信
缺点:
markdown
- 服务器必须保持每一个客户端的会话密钥,随着客户端的增多,服务器的内存压力也会增大
- 网站服务一般是通过多台服务器通过负载均衡提供服务的,客户端在此连接不一定会命中上次访问过的服务器,于是还要走完整的TLS握手过程
- session Ticket
服务器不在缓存每个客户端的会话密钥,而是把缓存的工作交给了客户端。客户端与服务器首次建立连接时,服务器会加密会话密钥作为ticket发给客户端,交给客户端缓存该ticket。客户端再次连接服务器时,客户端会发送ticket,服务器解密后就可以获取上一次的会话密钥,然后验证有效期,没问题的话回复会话开始通信。
session id和session ticket都不具备前向安全性,一旦会话密钥被破解或者服务器泄露会话密钥,前面劫持的通信密文都会被破解。同时对重放攻击也很困难
TCP
定义
TCP是面向连接的可靠的基于字节流的传输层通信协议
- 面向连接:是一对一才能链接
- 可靠的: 无论的网络链路中出现了怎样的链路变化,TCP 都可以保证⼀个报⽂⼀定能够到达接收端;
- 字节流: 消息是没有边界的,所以⽆论我们消息有多⼤都可以进⾏传输。并且消息是有序的,当前⼀个消息没有收到的时候,即使它先收到了后面的字节,那么也不能扔给应用层去处理,同时对重复的报⽂会自动丢弃。\
TCP头部格式
序列号: 在建⽴连接时由计算机⽣成的随机数作为其初始值,通过 SYN 包传给接收端主机,每发送⼀次数据,就累加⼀次该数据字节数的⼤⼩。⽤来解决⽹络包乱序问题。
确认应答号:指下⼀次期望收到的数据的序列号,发送端收到这个确认应答以后可以认为在这个序号以前的数 据都已经被正常接收。**⽤来解决不丢包的问题。 **
控制位
- ACK:该位为1时,确认应答的字段变为有效,TCP规定除了最初建立连接时的SYN包之外该位必须设置为1
- RST:该位为1时,表示TCP连接中出现异常必须强制断开连接
- SYN:该位为1时,表示希望建立连接,并在其序列号的字段进行序列号初始值的设定。在SYN报文段中指明MSS(最大报文长度)大小
- FIN:该位为1时, 表示今后不会再有数据发送,希望断开连接。当通信结束希望断开连接时,通信双⽅的主机之间就可以相互交换FIN位为1的TCP段
- URG:紧急
- PSH:PUSH过程
建立一个TCP连接是需要客户端与服务器达成的三个共识
TCP四元组(怎样确定一个连接)
- 源地址:32位,在IP头部, 作用是通过 IP 协议发送报文给对方主机
- 源端口:16位,在TCP头部中,作用是告诉TCP协议应该把报文发给哪个进程
- 目的地址:32位,在IP头部, 作用是通过 IP 协议发送报文给对方主机
- 目的端口:16位,在TCP头部中,作用是告诉TCP协议应该把报文发给哪个进程
最大连接数
UDP
UDP头部格式
TCP与UDP的区别
- TCP是面向连接的传输层协议,传输数据前要先建立连接;
UDP是不需要连接,即刻传输数据
- TCP是一对一的两点服务,一条连接只有两个端点
UDP支持一对一、一对多、多对多的交互通信
- TCP是可靠交付数据的,数据可以无差错、不丢失、不重复、按需到达
UDP是尽最大努力交付,不保证可靠交付数据
- TCP有拥塞控制和流量控制机制,保证数据传输的安全性
UDP没有,即使网络非常拥堵了,也不会影响UDP的发送速率
- TCP首部长度较长,会有一定的开销, 首部在没有使⽤选项字段时是 20 个字节,如果使用了选项字段则会变长的
UDP首部只有8字节,并且是固定不变的,开销较小
- TCP是流式传输,没有边界,但保证顺序和可靠
UDP是一个包一个包的发送,是有边界的,但可能会丢包和乱序
- TCP的数据大小如果大于MSS(最大报文长度)大小,则会在传输层进行分片,目标主机收到后,也同样在传输层组装TCP数据包,如果中途丢失了⼀个分片,只需要传输丢失的这个分片。UDP的数据大小如果大于MTU(最大传输单元)大小,则会在IP层进行分片,目标主机收到后,在IP层组装完数据,接着再传给传输层,但是如果中途丢了⼀个分片,在实现可靠传输的UDP时则就需要重传所有的数据包,这样传输效率非常差,所以通常UDP的报文应该小于MTU。
- TCP常用于FTP文件传输,HTTP/HTTPS
UDP常用于包总量减少的通信,如DNS、SNMP等、视频音频等多媒体通信、广播通信
TCP建立连接(三次握手)
建立连接是通过三次握手进行的
为什么是三次握手不是两次或者四次?
- 三次握手才能保证双方具有接收和发送的能力。
- 三次握手才能初始化socket、序列号和窗口大小。
- 三次握手的首要原因是为了防止旧的重复连接初始化造成混乱
在网络拥堵的情况下:
- ⼀个旧SYN报文比最新的SYN报文早到达了服务端;
- 此时服务端回一个SYN+ACK报文给客户端
- 客户端收到后根据自身的上下文,判断这是一个历史连接(序列号过期或超时),那么客户端就会发送RST报文给服务端,表示中止这一次连接
三次握⼿则可以在客户端(发送⽅)准备发送第三次 报⽂时,客户端因有⾜够的上下⽂来判断当前连接是否是历史连接
- 如果是历史连接(序列号过期或超时),则第三次握⼿发送的报⽂是 RST 报⽂,以此中止历史连接;
- 如果不是历史连接,则第三次发送的报⽂是 ACK 报⽂,通信双⽅就会成功建⽴连接;
- 同步双方初始序列号
序列号作用:
markdown
- 接收方可以去除重复的元素
- 接收方可以根据数据包的序列号按序接收
- 可以标识发送出去的数据包中,哪些是已经被对方收到的
- 避免资源浪费
如果客户端的SYN阻塞了,重复发送多次SYN报文,那么服务器在收到请求后就会建立多个冗余的无效链接,造成不必要的资源浪费
TCP断开连接(四次挥手)
双方都可以主动断开连接,断开连接后主机中的资源将被释放
- 客户端打算关闭连接,此时会发送⼀个TCP⾸部FIN标志位被置为1的报⽂,也即FIN报文,之后客户端进入FIN_WAIT_1状态。
- 服务端收到该报文后,就向客户端发送ACK应答报文,接着服务端进入CLOSED_WAIT 状态。客户端收到服务端的 ACK 应答报⽂后,之后进⼊ FIN_WAIT_2 状态。
- 等待服务端处理完数据后,也向客户端发送 FIN 报⽂,之后服务端进⼊ LAST_ACK 状态。
- 客户端收到服务端的FIN报⽂后,回⼀个ACK应答报⽂,之后进⼊TIME_WAIT状态。 服务器收到了ACK应答报⽂后,就进入了CLOSED状态,至此服务端已经完成连接的关闭。客户端在经过2MSL⼀段时间后,⾃动进入CLOSED状态,⾄此客户端也完成连接的关闭。\
为什么需要TIME_WAIT状态?
注:主动关闭连接的,才有TIME_WAIT状态
- 防止具有相同四元组的旧数据包被收到:2MSL后足以让两个方向上的数据包都被丢弃,使得原来连接的数据包在网络中都自然消失,再出现的数据包一定都是新建立连接所产生的
- 保证被动关闭连接的一方能被正确的关闭,既保证最后的ACK能让被动关闭方接收,从而帮助其正常关闭。
客户端四次挥⼿的最后⼀个ACK报⽂如果在⽹络中被丢失了,此时如果客户端TIME- WAIT过短或没有,则就直接进入了CLOSED状态了,那么服务端则会⼀直处在LASE_ACK状态。 当客户端发起建立连接的SYN请求报文后,服务端会发送RST报文给客户端,连接建立的过程就会被终止。
如果 TIME-WAIT 等待⾜够⻓的情况就会遇到两种情况:
TIME_WAIT过多有什么危害?
如果服务器有处于 TIME-WAIT 状态的 TCP,则说明是由服务器方主动发起的断开请求
该状态过多的危害主要有两种:
- 内存资源占用
- 对端口资源的占用,一个TCP连接至少消耗一个本地端口。
端口资源有限,如果发起连接的一方TIME_WAIT状态过多,沾满了所有端口资源,则会导致无法创建新连接
可以通过 net.ipv4.ip_local_port_range 指定端口开启范围,一般为32768~61000
为什么需要四次挥手?
关闭连接时,客户端享服务端发送FIN时,仅仅表示客户端不再发送数据了但是还能接收数据。服务端收到客户端的FIN报文时,先回一个ACK应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送FIN报文客户端来表示同意现在关闭连接。综上所述,服务端通常需要等待完成数据的发送和处理,所以服务端的ACK和FIN一般会分开发送,所以比三次握手多了一次
为什么TIME_WAIT等待的时间是2MSL?
MSL为报文最大生存时间。超过这个时间报文将被丢弃。TCP报文是基于IP协议的,而IP头中有一个TTL字段,表示IP数据包可以经过的最大路由数。 每经过⼀个处理他的路由器此值就减 1,当此值为 0 则数据报将被丢弃,同时发送 ICMP 报文通知源主机。MSL应该要大于等于TTL消耗为0的事件,以确保报文已被自然消亡。
TIME_WAIT等待两倍的MSL是因为网络中可能存在来自发送方的数据包,当这些发送方的数据包被接收方处理后又会向对方发送响应,所以一来一回需要等待两倍的事件\
重传机制
超时重传
- 在发送数据时,设置一个定时器,当超过指定的时间后,没有收到对方的ACK确认应答报文,就会重发该数据。数据包丢失 和确认应答丢失两种情况会发生超时重传
- 超时重传时间RTO的值应该略大于报文往返RTT的值。
- 当超时时间RTO较大时,重发就慢,丢了老半天才重发,没有效率,性能差
- 当超时时间RTO较小时,会导致可能并没有丢就重发,于是重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多的重发
RTT:数据从网络一端传到另一端所需的时间,也就是包的往返时间。 RTO:超时重传时间
- 网络是时常变化的,所以报文往返RTT的值也是经常变化的,所以超时重传时间RTO的值也应该是动态变化的
- 每当遇到一次超时重传的时候,都会将下一次超时时间间隔设为先前值的两倍。两次超时,就说明网络环境差,不宜频繁反复发送
快速重传
不以时间驱动,而是以数据驱动重传
工作方式:当收到三个相同的ACK报文时,会在定时器过期之前,重传丢失的报文段
SACK(选择性确认)
在TCP头部选项中加一个SACK的东西,可以将缓存的地图发送给发送方,这样发送方就可以知道哪些数据收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据
D-SACK
主要使用了SACK来告诉发送方有哪些数据被重复接收了
滑动窗口
- 为每个数据包确认应答的情况:包的往返时间越长,网络的吞吐量会越低。
- 窗口可以保证在往返时间较长的情况下,他也不会降低网络通信效率。我们可以指定窗口大小,即我们无需等待确认应答便可以继续发送数据的最大值
- 窗⼝的实现实际上是操作系统开辟的⼀个缓存空间,发送⽅主机在等到确认应答返回之前,必须在缓冲区中保留已发送的数据。如果按期收到确认应答,此时数据就可以从缓存区清除。
- 窗口大小一般是由接收方的窗口大小来决定的
发送方滑动窗口
四个部分,三个指针
- SND.WND:表示发送窗口的大小(由接收方指定)
- SND.UNA:是一个绝对指针,指向已发送但未收到确认的第一个字节的序列号
- SND.NXT:是一个绝对指针,指向未发送蛋壳发送范围的第一个字节的序列号
可用窗口大小:SND.WND - ( SND.NXT - SND.UNA )
接收方滑动窗口
三个部分,两个指针进行划分
- RCV.WND:表示接收窗口的大小,他会通告给发送方
- RCV.NXT:是一个指针,指向期望从发送方发送来的下一个数据字节的序列号
流量控制
窗口关闭
窗口关闭:如果窗口大小为0时,就会阻止发送方传递数据,直到窗口变为非0为止
接收方向发送方通告窗口大小时,是通过ACK报文来通告的。当发生窗口关闭时,接收方处理完数据后,会向发送方通告一个窗口非0的ACK报文,如果这个通告窗口的ACK报文在网络中丢失了,就会导致发送方一直等待接收方的非0窗口通知,接收方也一直等待发送方的数据,如不采取措施,这种相互等待的过程会造成死锁
解决方法:
TCP为每个连接设有一个持续定时器,只要TCP连接一方收到对方的零窗口通知,就启动持续计时器。如果持续计时器超时,就会发送窗口探测报文,而对方在确认这个探测报文时,给出自己现在的接收窗口大小。
- 如果接收窗口仍然为0,那么收到这个报文的一方就会重新启动持续计时器
- 如果接收窗口不是0,则死锁局面被打破
窗口探测的次数一般为3次,每次大约30-60秒,如果三次过后接收窗口还是0的话,有的TCP实现就会发RST报文来中断连接
糊涂窗口综合症
如果接收方腾出几个字节并告诉发送方现在有几个字节的窗口,而发送方会义无反顾的发送这几个字节
eg: 就好像⼀个可以承载 50 人的⼤巴⻋,每次来了⼀两个⼈,就直接发⻋
该现象可以发生在发送方和接收方:
- 接收方可以通告一个小的窗口
- 发送方可以发送小数据
解决方法:
- 让接收方不通告小窗口给发送方
- 让发送方避免发送小数据
Nagle算法是默认开启的,当需要发送小数据时,需要关闭该算法
拥塞控制
在网络出现拥堵时,如果继续发送⼤量数据包,可能会导致数据包时延、丢失等,这时TCP就会重传数据,但是⼀重传就会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,这个情况就会进入恶性循环被不断地放大** **
- 目的:避免发送方的数据填满整个网络
- 拥塞窗口:为了在发送方调节索要发送的数据量,根据网络的拥塞程度动态变化
只要发送方没有在规定时间内接收到ACK应答报文,也就是发生了超时重传,就会认为网络出现了拥塞
变化规则:
- 只要网络中没有出现阻塞,就会增大
- 网络中出现拥塞,就减少
- 发送窗口swnd=min(拥塞窗口cwnd,rwnd接收窗口)
- 控制算法:
- 慢启动
一点一点的提高发送数据包的量。每当发送方收到一个ACK,拥塞窗口cwnd的大小就会加1
慢启动门限ssthresh状态变量,一般来说ssthresh大小为65535字节
markdown
- 当拥塞窗口cwnd < ssthresh时,使用慢启动算法
- 当cwnd >= ssthresh时,使用拥塞避免算法
- 拥塞避免
每收到一个ACK时,cwnd增加1/cwnd。
发生重传机制时,就进入了拥塞发生算法
- 拥塞发生
拥塞发生算法发生时ssthresh和cwnd的值会发生变化
超时重传时:
markdown
- ssthresh设为cwnd/2
- cwnd重置为1
快速恢复时:
ini
- cwnd=cwnd/2
- ssthresh = cwnd
- 进入快速恢复算法
- 快速恢复 - 拥塞窗口cwnd=ssthresh + 3(3的意思是确认有3个数据包被收到了) - 重传丢失的数据包 - 如果再收到重复的ACK,那么cwnd增加1 - 如果收到新数据的ACK后,把cwnd设置为第一步中的ssthresh的值,再次进入拥塞避免状态