网络编程
TCP
一、确认应答ACK
序号和确认序号
二、超时重传
如果ACK丢了就会导致接收方收到一样的数据,TCP会自动在接收缓冲区里根据序号进行重传,保证接收方不收到重复数据
三、连接管理
- 三次握手:建立连接
- 为什么要三次握手?
- 为了可以投石问路,确认当前网络环境是通畅的,可以进行可靠传输
- 四次挥手:断开连接
四、滑动窗口
1. 滑动窗口是在保证可靠性的前提下,尽量提高传输效率
2. 原理
因为确认应答机制,要确认上一个ACK到达后,再发送下一个数据,这样效率太低
滑动窗口就是批量发送数据,例如一次发四组数据1-1000、1001-2000、2001-3000、3001-4000,四组发完后统一等待ACK
等必须等!不然ACK和可靠传输形容虚设!可以同时等多组数据节省时间
3. 运行
一次批量发送数据为N,N称为窗口大小
收到一组数据(1-1000)的ACK即可发送下一组数据(4001-5000),不需要等到所有组数据的ACK
这个过程就像一个大小为4的窗口在向后滑动,收到一组就往后划一组
当前的窗口越大,可以认为传输速度越快
如果丢包了怎么办?
情况1:ACK丢了,2001的ACK没到,3001的ACK到了怎么办?
情况2:数据丢了怎么办?
情况1:第一组的ACK1001丢了(里面涵盖的信息是已接收到1-1000),在发送4001前,发现收到了一个2001,没有收到1001。
2001的意思是2001前的数据都已经确认收到了(1-2000),所以1-1000肯定收到了,收没收到ACK无所谓。ACK确认序号的特定含义,保证了后一条ACK能涵盖前一条,类似于闯关解锁,到了后面的关,意思前面已经解锁了。没事!不用处理!
情况2:1001-2000数据丢了。
接收方会向发送方反复索要1001-2000数据
索要多次后,就会触发重传
快重传:只重传丢了的一块数据,效率还是比较高的
五、 流量控制
- 滑动窗口的延伸,目的是保证可靠性
- 衡量接收方的数据处理速度和能力,看接收方的接收缓冲区的剩余空间
- 这个控制是会调整的的,通过ACK告知发送方(16位窗口大小)发送方会调整发送速度(窗口大小)
- 如果发送方发贼快,接收方处理不来,就会把新发的包丢了,发送方需要重传
- 当窗口大小为0,发送方不发送了,但是接收方还在处理,所以不会一直是0
六、拥塞控制
- A可以发多块不光取决于B的处理能力,也取决于中间链路的能力,拥塞控制衡量的是发送方到接收方这个链路之间的拥堵情况
- 拥塞控制的处理方案就是通过实验,逐渐调整发送速度,找到合适的值或范围
A开始的时候以非常小的窗口发送数据,如果数据顺利到达,就逐渐加大窗口(指数增长),到一定程度后,就会进入线性增长,增长到一定程度就会丢包。一旦丢包,发送方就会让窗口变小到初始的窗口大小(旧版本,新版本是到一半的大小),重复指数+线性增长这一过程。
因为网络环境是复杂的,一旦出现丢包,只是把速度降一点,或降得太慢,会出现持续性的丢包,影响通信。一下子让窗口变得很小,是期望这一次通信一定成功。
最终滑动窗口的大小=min(拥塞窗口,流量控制窗口)
期望的最理想效果:窗口大小在阈值和丢包窗口大小之间
丢包了就视为拥堵
七、延迟应答
流量控制的延伸,流量控制是踩刹车,发送方不要发太快;延迟应答就是让窗口更大一点。
接收方不立即回答,稍微晚一点回答。
八、捎带应答
延迟应答的延伸
- 一问一答:客户端一个请求,服务器返回一个对应;
- 多问一答:上传文件;
- 一问多答:下载文件;
- 多问多答:直播;
一般回应的时候会回两个:ACK和程序响应,两个速度不同,ACK是内核相应立即执行,程序需要执行相关代码才能返回。
因为有延时应答,ACK与程序响应的时机可能重合了,就可以把他们合二为一。
九、面向字节流→粘包问题(不仅仅TCP存在这个问题,其他面向字节流的机制如读文件也存在)
TCP粘包粘的是应用层数据报,在TCP接收缓冲区中,若干个应用层数据包混在一起了,分不出谁是谁。
TCP发数据有个报头,后面才是应用层数据,接收方用read方式读取缓冲区数据,取出来就是若干个字节,从哪里取到哪里是完整的应用层数据呢?
解决方案:在应用层协议里加入包之间的边界
这是应用层数据的问题,与TCP无关。如果自己实现一些库/框架,直接使用TCP,就需要考虑粘包问题。
十、TCP异常处理
1. 进程中止
- 在进程毫无防备的时候突然结束进程,这时候进程的TCP连接是什么样的?
- TCP连接是通过socket建立的,socket本质上是进程打开的一个文件,文件其实就存在于进程的PCB里面有个文件描述符表
每打开/关闭一个文件,都在文件描述符表里增加/删除一项
如果直接杀死进程,PCB就没了,里面的文件描述符表也没了,此处文件相当于自动关闭,会触发四次挥手
2. 机器关机
正常流程的关机,会让操作系统,杀死所有进程,然后关机,同1
3. 拔电源/断网
操作系统没有任何反应时间,没有措施,偷袭成功
- 接收方断电
接收方断电,发送方收不到ACK,超时重传,几次重传失败后重新建立连接,建立连接失败,放弃。 - 发送方断电
接收方会时不时给发送方发送一个小的报文,无实际数据,只为了触发ACK。
通过探测报文,发现A不返回ACK,重传、重连、放弃。
- 如何利用UDP实现可靠传输?
- 实际上就是在机制上复刻TCP