TCP中的一些核心机制: 有链接,可靠传输,面向字节流,全双工
它的格式:
一 确认应答
确认应答是保证可靠性传输的核心机制
关键就是接收方再收到消息之后,给发送方,返回一个应答报文(ACK,acknowlage),表示自己收到了,
为了防止网络上的消息出现后发先制的情况, 根据确认序号进行编号,TCP的针对消息的序号,不是按条进行编号,而是按照字节的方式进行编号
二丶超时重传
相对于确认应答的补充,确认应答是网络一切正常的时候,通过ACK通知发送方我收到了,如果出现了丢包的情况,超时重传就起到了效果
①一种是发送的消息丢失
②另一种是发送方返回的ACK发生丢失
当发送方收到了重复的消息,TCP内部会有一个去重的操作, 接受方收到的数据会先放到操作系统内核的"接受缓冲区"中,接受缓冲区可以视为是一个内存空间,并且也可以视为是一个阻塞队列。收到的新数据TCP就会根据序号,来检查这个数据是不是在缓冲区中是否已经存在,如果不存在,就放进去,如果存在,直接丢弃, 保证应用程序调用Socket API一定是不重复的!!!
三丶连接管理(重点)
1) 如何建立连接
三次握手:客户端与服务器之间,通过三次交互,完成了建立连接的过程
三次握手客户端一定是主动发起的一方,服务器端是接受的一方
TCP的状态有很多,这里说两个比较重点的
LISTEN:表示服务器启动成功,端口绑定成功,随时可以有客户端发起连接
ESTABLISHED:表示客户端已经建立连接成功,随时可以进行通信
①三次握手有啥用?和可靠性有啥关系?
三次握手就相当于"投石问路",检查一下当前这个网络的情况是否满足可靠性传输的基本条件,更具体的来说,就是检测通信双方的发送能力和接受能力是否都正常
2)如何断开连接
四次挥手
四次挥手可以是客户端发起的断开,也可以是服务器发起的断开(这里的图是客户端发起)
四次挥手中,中间两次有时候能合并(有时候合并不了)
①不能合并的原因: 在于B给A发送FIN的时机是不同的!! 四次挥手中,A给B发送的ACK,是系统内核负责的,B给A发送的FIN是用户代码负责的(B中调用了socket.close()才会触发FIN),如果这两次的操作的时间差较小,可能会合并
②两个重要的状态:
③TIME_WAIT应该持续多长时间呢?
设定时间是2MSL
④MSL:表示网络上的两点之间,传输的需要的最大时间,这个时间也是系统上可以配置的参数,一个典型的设置就是60s
四丶滑动窗口
滑动窗口存在的意义是在保证可靠性的前提下,尽量提高传输效率,本质就是"批量的发送数据",一波发送数据,一波等待ACK
"滑动"的意思是,并不用把N组数据全部等到了,才继续发送,而是收到了一个ACK,就继续往下发一组
当窗口越大的时候,我们认为发送效率就越快~
当前有一个核心问题:丢包
①如果ACK丢失
在发送方收到5001的时候,意味着1-5000的数据全部收到了,3001-4001被丢包也毫无影响,ACK确认序号的特定含义,就保证了后一条ACK就能覆盖前一条~ ,因此我们认为不做处理
②数据丢失
由于1001-2000这个数据丢失,所以B反复索要1001这个数据~~即使A给B已经往后发了,这个时候仍然索要1001,当索要若干次后,A就明白了,数据丢失就会触发重传~~
五丶流量控制
流量控制是滑动窗口的延申,目的是保证可靠性
在滑动窗口越大,传送速率越高,但是不光要考虑发送方,还要考虑接受方的,如果发送方发的太快,接收方根本处理不过来,接收方就会把新收到的包丢弃,还是的重传.
流量控制的关键就是能够衡量接受方的处理速度,防止出现上述的丢包
六丶拥塞控制
拥塞控制,也是滑动窗口的延伸,也是限制滑动窗口的发送速率,拥塞控制衡量的是,发送方到接受方,这整个链路之间的拥堵情况(处理能力);
A开始的时候以一个较小的窗口来发送数据,如果数据很流畅的到达,就增大窗口,如果加大到一定成度出现丢包,(丢包就意味着通信链路出现拥堵了),这个时候在减小窗口~~
滑动窗口的最终大小=min(拥塞窗口,流量控制窗口)
先通过指数增长,增长到阈值之后在进行线性增长
七丶延时应答
相当于流量控制的延伸~流量控制是踩住了刹车,是发送方,不要发的太快,延时应答,就想在这个基础上,让窗口再大一点
八丶捎带应答
捎带应带又是延时应答的延伸~
延时应答的存在导致ACK不一定立即就返回,如果当前的延时应答,导致ACK的返回时机和当前代码中返回的响应时机重合了!!,就可以把这个ACK和响应数据一起发送,合二为一
九丶面向字节流
粘包问题:TCP粘包指的是粘的应用层数据报.在TCP接收缓冲区中,若干个应用层数据包混在一起了,分不清谁是谁.
十丶TCP的异常处理