TCP提供的是面向连接的可靠服务,基本上提供的功能应有尽有。
TCP提供的是全双工通信,发送的同时也能接受。TCP 连接的两端都有发送缓存和接受缓存,应用程序发送消息进入缓存之后就可以干自己的事情了。
TCP要搞接受缓存的根本原因是应用程序不一定来得及处理完那么多数据。
TCP是面向字节流的,意思就是它不需要自己操心报文的到达啥的。
同时缓存还可以用来处理乱序到达的字节。
TCP能从缓存中放入报文段的数据数量取决于MSS,Maximum Segment Size,这个大小是根据本地主机的链路层来设置的。省得本地主机再切。
值得注意的是,MSS是TCP报文段中的数据段的最大长度,而不是整个TCP报文段的最大长度,也就是不包含首部。
5.3.1 TCP段
5.3.1.1 TCP报文段序号与确认序号
5.3.1.2 TCP段结构
选项和填充的宽度仅为示意,并非固定为 24 位和 8 位;数据部分的长度也可变。
序号:每一个报文段的实质是一连串的字节,我们给这些字节编号之后,首部中的序号段表示该报文段所携带数据的第一个字节的序号,而不是报文段自身的编号。
TCP采用累积确认,因此确认序号不能是第一个字节的序号;我们把它设置为了期待收到的下一个字节的编号,比如我已经收到了字节0-999,那么发送的ACK确认序号就是1000。
你可能会问我们为什么需要ACK标志,这是因我们第一次建立连接向对方发送消息的时候没有确认任何信息?你可能又会说为什么不把ACK序号设为0,但是序号是循环使用的, 用完了之后就回到了0了,所以0本身也是个有效的序号。
SYN=1表示这个报文段刚好是用来建立请求连接,或者回应建立请求连接的。
紧急指针和URG标志位:RFC9293表面新应用不该使用紧急机制,作为历史包袱即可。
FIN=1 用于断开连接过程
RST=1代表出现严重差错,必须释放并且重新连接
接受窗口字段表示接受方的缓存剩余空间,用于实现流量控制。
保留字段的值目前为0。
5.3.2 TCP连接管理
5.3.2.1 TCP连接建立过程
TCP是全双工通信,这意味着对方在像我们发送的时候我们也在不断向对方发送消息,所以ACK本身是可以在帮别人发送消息的时候顺带完成的,通过确认序号。
主机1首先会向主机发送第一次握手,此时ACK=0,SYN=1,这个特殊的报文段被称为SYN 报文段.
然后主机B会回复二次握手,此时ACK=1,SYN=0,这个报文段被称为SYNACK 报文段.
对于普通的空数据报文段,是不会消耗序号的,但是 SYN 报文段和 SYNACK 报文段却需要消耗序号,这是为什么呢?
这是因为序号的本质是用来确认我们收到了某条消息。在握手阶段中,我们需要确认每一条消息都被收到。但是在传输过程中,我们不需要对ACK再发送ACK,不然你还可以发送ACK的ACK的ACK,有点没完没了。累积确认的一个好处就是ACK丢失了也不要紧。
5.3.2.2 TCP连接拆出过程
TCP的断开连接,通常称为四次挥手,过程如下:
用户在发送完最后一个数据段之后,发送一个FIN段,其中FIN=1,序号要+1,这个段本身不再发送数据,并且后续也不能发送任何数据.
服务器会返回一个FINACK,请注意FINACK是能返回数据的。然后服务器可能会继续发包发送数据,一直到服务器把所有需要的数据发完为止。
服务器发完之后会反向向用户发送FIN,然后用户回FINACK,具体细节相同。
5.3.3 TCP可靠传输
5.3.3.1 TCP的可靠数据传输机制
TCP靠序号和累积确认避免了乱序。
TCP会超时重传,采用了选择重传协议。
TCP有校验和,因此实现了差错检测,有错就扔掉不发送ACK
5.3.3.2 TCP计时器超时时间设置
计时器的合适的超时时间很重要,我们采用RTT采样方式,RTT采样是间隔采用,而不是每发一个报文都采用,而且重传的报文永远不纳入采样,只有单次发送收到的被纳入采样。
显然采样会波动,
这是一个迭代公式。
超时时间的设置也有讲究,比较传输时间的波动情况也要考虑,我们定义
TCP如果仅仅依赖超时重传存在一些问题,会导致等待较长时间才会重传。我们采用重复ACK加快重传。
下面我们讲ACK策略:
假设所有所期望的报文段按序到达,TCP接收方会延迟发送ACK,否则才会确认。
5.3.4 TCP流量控制
TCP采用滑动窗口协议,但是流量动态变化。发送端的发送窗口总是确保不大于接受端发回数据的接受窗口(还收到拥塞控制)
5.3.5 TCP拥塞控制
拥塞是指太多主机太快地发送数据,超过了网络的处理能力。拥塞会导致:
数据分组通过网络的时延显著增加
由于队列满而导致大量分组被丢弃
TCP的拥塞控制是从端到端的角度推断网络是否拥塞。基本策略是网络未拥塞式,加性增加窗口大小,拥塞时乘性减小大小从而维持平衡。
TCP发送端维护一个拥塞窗口的长度变量Congwin
拥塞算法包含四部分:
慢启动
拥塞避免
快速重传
快速恢复
慢启动:开始发送数据时,拥塞窗口用非常快的形式增长,先设置为MSS的值,然后每收到一个确认,Congwin增加一个MSS. 所以我们连续发的包会越来越多,收到数据会越来越快。直到达到了预设的Threshold,这个时候我们要慢慢增加。
接下来进入拥塞避免阶段,拥塞避免阶段仍然在不断加高自己的容量。
拥塞避免:每经过一个RTT,Congwin的值+1 MSS。如果计时器超时了,我们令Threshold=Congwin/2,然后让回到1
因为超时情况比较特殊,如果后续的包到达了,可能丢包的只是个别,但超时说明情况相对研究一下,因此回到1重新探测。
快速重传:收到3次重复ACK的时候。我们会重传一次ACK索期待的报文段
快速恢复:快速恢复配合快速重传使用。它和拥塞避免的差别是窗口不回到1,而是回到Threshold然后进入拥塞避免状态