socket编程——TCP数据传输的可靠与稳定性
尽管大家都相信TCP数据传输是稳定的,但是什么原因保证了TCP数据传输的稳定性呢?笔者对其原因做了一些归纳整理,下面将分别对其展开
ACK确认机制
前文TCP连接与断开对TCP协议结构说明时指出,每条TCP报文都包含Sequence与Acknowledge字段。那么这两个字段是怎么变化的呢?下面下来看一张用wireshark捕获的TCP数据流
该图展示了TCP建立连接、数据交互、断开连接过程时Sequence与Acknowledge字段的变化,可知Acknowledge与Sequence值随着发送字节数变换而变化,注意:这里sequence从0开始,是因为wireshark工具做了相对处理,可以右键菜单中的protocol preference 中取消掉relative sequence number就可以看到原始的序列号
报文首部校验
TCP检验和由发送端计算,在接收端验证。其目的是为了发现数据在传输过程中的任何改动,若接收端校验不通过则丢弃数据。TCP的校验和是必需的,UDP的校验和可选。RFC 793协议规定校验方式为:首先把伪首部(包含发送方与接收方的IP、保留字节、传输层协议号、报文总长度)、TCP报头、TCP数据分为16位的字(具体如何分配?),累加取反获得校验和
超时重传
为了应对网络传输过程中发生的数据包丢失,TCP协议规定了一种数据重传机制,发送方在一段时间内没有收到接收的ack时,数据发送方重新发送超时数据,所以如何确定超时时间就非常关键。
早期RFC793定义,首先通过多次采样记录多次RTT(数据从发出到收到ack的时间),然后做平滑计算,获取均值,最后通过比较最大,最小超时时间与均值,取出最小数作为最终的超时时间。但是早期的算法也有许多不合理的地方如RTT是否计算重传时间,若不计算,当网络延时较大,而RTO(Retransmission TimeOut)又较小等等问题,在RFC6289中Jscobson/Karels改进了算法并被延用
滑动窗口
滑动窗口是TCP对数据收发的流量控制。TCP接收方首部的Windows字段保存了当前可接收到的最大数据量,发送方会根据接收方返回到ack确认接收方的接收能力,通过控制滑动窗口的大小来控制发送数据的大小,来保证接收方可以处理。其结构如下图所示
其中黑框就是滑动窗口,窗口的具体大小由接收端的接收能力(rwnd)与拥塞控制窗口(cwnd)的最小值决定,其计算公式如下
swnd = min(rwnd,cwnd*mss)
由于Linux内核中cwnd以包为单位,所以需乘上mss(最大分段单元)
分段传输
TCP数据发送时没有数据量的限制,有多少数据就能发送多少数据到接收端,那么是不是所有数据都是一股脑的发出去呢?并不是这样,如果研究wireshark的TCP包就能发现,每包TCP数据量最多只有1460byte,为什么是1460byte呢?由于以太网规定了最大传输帧(MTU)为1500byte,TCP、IP协议首部分别占20byte,所以1500-20-20=1460,这就是为什么每包中只能传输1460byte,超过1460byte的数据将分多次发送。
清风 | 文 【原创】
如果本篇博客有任何错误,请批评指教,不胜感激 !