目录
一、UDP协议
① 协议实现
② 协议特性
③ 编程影响
④ 基于UDP的应用层协议
二、TCP协议
① 协议实现
② 协议特性:面向连接、可靠传输、提供字节流传输服务
面向链接:
1、三次握手建立连接:
2、四次挥手断开连接:
3、TCP连接管理中的保活机制:
可靠传输:
1、流量控制:滑动窗口机制
2、停等协议:
3、回退N步协议:
4、选择重传协议:
5、拥塞控制:
6、快速重传协议:
字节流传输:
1、粘包问题:
一、UDP协议
UDP是User Datagram Protocol的简称,中文名是用户数据报协议
① 协议实现
就是在应用层交付给自己的数据前封装了一个UDP报头
16位源端口号,16位目的端口号:描述通信俩端进程是谁
16位数据报长度:长度字段指定了该数据报的总长度(该字段大小也限制了传输数据报长度必须小于64K-8)
16位校验和:校验数据一致性
② 协议特性
无连接:通信时,不需要建立链接,只要知道对方地址就可以发送数据
不可靠:不保证数据有序,且安全的到达对端(没有丢包检测以及重传机制)
面向数据报:整条交付,有最大长度限制的传输方式
③ 编程影响
UDP传输数据有最大长度限制,必须小于64K-8,如果数据过大就需要在应用层进行分包操作
UDP不保证数据有序且安全的到达对端,因此传输多个数据时, 应用层需要做出包序管理(保证传输包的顺序),如果对可靠有要求,则需要再应用层实现对应的丢包检测以及重传机制
UDP传输是整条交付的,不会交付半条或者多条数据,在应用层接收数据时,缓冲区就必须定义的足够大,能够确保至少获取完整的一条数据。
④ 基于UDP的应用层协议
NFS:网络文件系统
TFTP:简单文件传输协议
DHCP:动态主机配置协议
BOOTP:启动协议
DNS:域名解析协议
二、TCP协议
传输控制协议
(Transmission Control Protocol").
人如其名
,
要对数据的传输进行一个详细的控制
① 协议实现
32位序号:
4位头部长度:以4字节为单位描述TCP报文头部长度,TCP报头最长是60字节,最小20字节
解析过程:先取出20字节固定长度数据,然后根据头长取出选项数据
(这20字节就是结构的前五行,每行4字节)
说白了这个字段就说明TCP传输层在这条数据里面占多少,拿出来之后剩下的就是应用层数据
6位保留:展示未使用
6位标志位:FIN、SYN、RST、PUSH、ACK、URG
FIN:表示断开链接
SYN置1:这个标志位表示一个连接建立请求
RST:reset 表示重新建立请求
PUSH:要求 尽快将数据取出
ACK:确认应答
URG:紧急指针
16位窗口大小:用于实现滑动窗口机制,进行流量控制
16位校验和:二进制反码求和算法,校验数据一致性
16位紧急指针:指向紧急优先带外数据的结束位置
② 协议特性:面向连接、可靠传输、提供字节流传输服务
面向链接:
通信前,要先建立链接,确保双方都是在线,具有数据收发能力的。
连接管理:三次握手建立链接,四次挥手断开链接
1、三次握手建立连接:
通信前,要先建立链接,确保双方具有数据收发能力的。
为什么握手是三次?
俩次不安全,四次没必要
俩次不安全:通信双方都要确认双方是否具有数据收发能力,因此都要进行SYN确认
1、合并前俩步,有可能SYN会延迟到达,与重发的SYN形成冲突
2、防止恶意攻击,比如客户端发送SYN后直接退出
四次没必要(没必要发送俩次报文,再一次回复中将对应比特位置一即可)
握手失败了,俩端是如何处理的:
第一次握手失败:客户端会重传请求SYN
第二次握手失败:服务端在等待最后一次ACK超时后发送一个RST然后释放资源。
客户端会重传SYN
第三次握手失败:服务端在等待最后一次ACK超时后发送一个RST然后释放资源。
2、四次挥手断开连接:
通信结束了,会有一个断开连接过程,避免出现意外情况。
FIN请求的功能:只能表示不再给对方发送数据(不代表不接收数据)
CLOSE_WAIT:等待关闭,对方发送了FIN包,已经不再给自己发送数据,上层如果这时候还在继续recv,则会读完缓冲区数据后,不再阻塞,而是返回0。这种情况下就是等待上层针对这种情况处理。
1、挥手为什么是四次:
1、FIN请求只能表示主动关闭方不再发送数据,不代表不再接收数据,因此,被动关闭方收到FIN并进行确认后,还有可能会继续发送数据等待上层不再发送数据了,也要关闭套接字了才会发送FIN包,因此中间的ACK和FIN不能进行合并
2、一台主机上出现了大量的CLOSE_WAIT状态连接,是什么原因?
只有收到了FIN请求并进行了确认回复的连接会进行CLOSE_WAIT,
但是再后续没有进行close操作导致一直处于CLOSE_WAIT状态,无法发送FIN,
原因就是代码中没有针对断开连接的套接字进行关闭处理。
3、TIME_WAIT状态有什么用,为什么不直接关闭套接字释放资源?
TIME_WAIT是主动关闭方在收到被动关闭方发送ACK和FIN之后,再向被动关闭方发送了一个ACK确认后,自身处于的一种状态TIME_WAIT,随后再等待2个MSL(报文在网络中存在的最大生命周期,默认60s)之后成为CLOSED状态
可是为什么要这样呢?
因为有这样一个可能,就是被动方没有收到最后一次ACK(上图中的红叉),那么它就会给主动方重新发送一份FIN请求,然后主动方又会重新发送一个ACK,存在这样一个确认的过程。
并且,如果此时发送ACK之后退出了,没有TIME_WAIT,主动方直接关闭了套接字释放资源,有可能出现新启动的套接字使用了之前相同的地址信息,而后续被动关闭方又会重传FIN,就会导致上一次通信因为ACK最后一次丢失,遗留的问题(重传FIN)对新链接造成影响。
所以需要等待俩个MSL时间,针对有可能存在的FIN重传进行处理,并保证上一次通信的所有数据都消失在网络中。
4、一台主机上出现了大量的TIME_WAIT状态连接,是什么原因,如何处理?
TIME_WAIT是主动关闭方发送最后一次 ACK后进入的状态,等待一段时间是为了处理有可能因为FIN丢失导致的FIN重传的处理。
因此一台主机出现大量TIME_WAIT连接,是因为主机上大量的主动关闭了连接,常见于爬虫服务器
而TIME_WAIT等待时间是可配置的,可以将时间设置的更短,或者有个套接字选项,叫做地址重用。setsockopt()
3、TCP连接管理中的保活机制:
连接断开有个信息:recv会返回0,send会触发异常
TCP通信中,如果客户端和服务端通信频率并不高,中间突然网断了,没有四次挥手的机会,如果两端通信频率很低,可能需要很久才会发现
在通信中,客户端与服务器若长时间无通信(默认7200s),则TCP服务器会自动的向客户端发送保活探测心跳包,要求对方进行响应(默认每隔75s),若连续多次都没有收到响应(默认9次),则认为连接断开。 这些时间都是可以配置的(如果嫌时间不合理的话)
不是每个连接断开都会有四次挥手
有:正常关机,程序关闭
无:机器断电、突然断网
可靠传输:
面向连接——确保双方都具有数据收发的能力,通过很多特殊机制实现
安全:
丢包检测机制--确认应答机制:接收方要针对收到的每一条数据进行确认回复
丢包重传机制--超时重传机制:等待确认回复超时则重传
有序:
协议字段中的序号&确认序号:进行包序管理,有序交付
校验和字段:校验数据一致性,不一致则丢弃,要求重传
性能的挽回:
TCP为了保护可靠传输,牺牲了传输性能,但是有些性能损失是没有必要的
1、因为发送数据过多,导致对方缓冲区溢出而丢包
1、流量控制:滑动窗口机制
作用:进行流量控制,避免因为发送方发送数据过多导致丢包
关键点:协议字段中的窗口大小 (在6位标志位后面的16位窗口大小)
窗口大小字段:接收方进行数据发送或者确认回复的时候,
告诉对方最多给自己发送多少数据(大小<接收缓冲区空闲空间大小)
滑动窗口机制实现: 通信中套接字会维护一个发送窗口&接收窗口
MSS:最大数据段大小,一个TCP报文的最大数据大小,
通信双方在三次握手阶段会协商MSS大小,取双方较小的一个值
MTU:链路层限制的最大传输单元,以太网默认1500字节
2、因为网络状况的突变,导致大量的丢包 重传
3、因为确认应答丢失所导致的重传
2、停等协议:
发送方发送一条数据后,收到回复才会发送下一条数据
适用于网络状况较差的场景
3、回退N步协议:
滑动窗口机制决定了TCP数据传输可以管线化传输,可以连续发送多个报文,而在传输过程中,如果出现了丢包,回退N步协议,指的是从丢包的这个数据开始重新对数据进行传输
适用于网络状况一般的场景
4、选择重传协议:
传输过程中,丢包了,哪个包丢了,就对哪个包重传
适用于网络较好的场景
5、拥塞控制:
避免因为网络状况突变,因为网络拥塞而导致大量丢包的情况
关键点:进行网络状况的探测
你的电脑已经卡爆了,你还给它塞了很多东西让它接收,丢包的情况不得事丢上加丢?
TCP引入慢启动机制,先发一点数据,探探路,摸清当前的网络情况,速度好了再快增加
刚开始一次传一个包,指数级增长,到达刚开始的这个阈值之后,就开始线性增长,直到出现丢包情况,把阈值进行调整之后(变为窗口的一半),速度就重新降为1,重新开始刚才的过程,不过这次到达阈值之后的线性增长斜率会平缓一些。
拥塞窗口:控制发送数据量的基准
发送数据发小<=min(滑动窗口大小,窗口大小)
拥塞窗口,一般初始值大小为1
拥塞窗口的思想:慢启动,快增长
拥塞窗口从初始值开始进行指数级增长,达到阈值时进行线性增长
6、快速重传协议:
再数据传输过程中,接收方接收数据的时候,并没有接受到起始接收序号的数据,而是接收到了后边的数据(再第一条数据之前先收到了第二条数据,可能前面走的数据还在路上,后面走的先到了)
传统方法——超时重传,接收方不会对后面的数据进行处理,必须要等前面的数据到了才处理后面的数据,接收方就一直慢慢等,直到超时情况出现,给发送方发送一个前面数据的超时重传信号,让把前面的数据重新发一下(效率太低了)
因此,快速重传:接收方为了提高效率,会给发送方回复一个第一条数据的序号确认,接收后续数据的时候都会进行同样的序号确认(收一个后面的数据就给那边说,第一个数据还没莱来呢),发送方在收到三条(三次作为一个基准次数)第一个数据的序号确认之后,则会对第一条数据进行重传。
可靠传输:
1、保证可靠:面向连接、确认应答机制、超时重传机制、序号、确认序号、校验和
2、如何避免丢包?
滑动窗口机制 + 拥塞控制
3、如何进行性能挽回?
快速重传协议:避免每次重传都需要等待超时才进行
延迟发送机制: 解决频繁的小数据发送效率较低的情况,减少了IO次数提高了效率(缓冲区少了就多等等,等发送缓冲区的数据多了再发)
延迟应答机制:基于确认应答机制,接收方需要对发送方的每一条数据进行确认回复。而如果直接对数据进行确认回复,大概率数据在缓冲区并没有被取出,因此这时候的回复会导致窗口大小变小,网络的吞吐率降低了,因此设计者就设计延迟一会应答,这段延迟的时间中,应用程序就有可能将数据取出,保持窗口不变,吞吐率不变,尽可能的总是以最大速率传输数据。
捎带应答机制:接收方再收到发送方发来的数据之后,把接收的确认序号捎带在发送的数据一起发送过去。尽可能减少空报文的传输。
字节流传输:
传输的时候,对数据以字节为单位进行编号,进行传输,不限制传输大小
1、粘包问题:
数据在缓冲区中堆积,将多条数据当作一条数据进行处理的过程
粘包产生的本质原因:是数据之间缺乏边界管理
TCP粘包问题:再传输层,并不管传输的什么数据,只管从缓冲区中取出合适大小
的数据进行操作,没有边界管理。
解决方案:在应用层,程序员对数据进行边界管理
边界管理:明确一条数据从哪儿开始,到哪儿结束
1、特殊字符间隔:需要对数据中的特殊字符进行编码,避免歧义
2、数据定长:数据固定长度,缺陷就是需要以最大长度定线(浪费较多,效率低)
3、数据采用TLV格式:在应用层头部中定义数据的长度(先取头部,根据头部中的长度,决定取多少数据)
TCP粘包了解吗?UDP粘包问题怎么解决?
UDP根本没有粘包问题,因为UDP的面向数据报传输方式,本身就是一次最多交付一条数据(UDP本身就有数据的边界管理)
UDP的sendto接口发送数据,将数据放到发送缓冲区之后,会立即封装头部进行发送。
More translations of反弹in EnglishARCore 支持的设备