1.TCP的段结构(在传输层称报文段)
说明:序列号和ACKNum不是段的编号,而是数据字节来计数
序列号指的是segment中第一个字节的编号,而不是segment的编号,举例有1K个字节的数据拆成两个segment,第二的
segment的编号是501。
ACKNum:希望收到的下一个字节的序列号,采用的累计确认的方式:该序列号之前的所有字节均已被正确接收到
接收方处理乱序到达的Segment,TCP规范中没有规定,由TCP的实现这做出决策。
示例(远程登录):
两台主机跑telnet
输入字符C后,生成一个段,序列号为42,确认号为79,(这两个数字是建立连接的时候随机选择的,跳过了建立连接的过程),
这个段的序列号是42期望收到的下一个字节的序列号是79,里面装的数据是C。
主机B会回传这个字符,返回的段序列号是79,ACK为43,(刚刚段的序列号是42,里面装了一个字符,一个字符占用一个字节)
,43表示下一个期望收到的序列号是43,这同时表示43之前的字节都已经正确收到了。
主机A再发一个确认,这个确认不带数据,序列号为43,使用这个确认刚刚的消息。
2.TCP的可靠数据传输
TCP在IP层提供的不可靠服务基础上实现可靠数据传输服务。
流水线机制
累计确认机制
TCP使用单一重传机计时器
触发重传的事件 超时+收到重复ACK
2.1 问题一:如何设置定时器的超时时间
大于RTT (RTT是变化的)
过短(不必要的重传)
过长(对段丢失时间反应慢)
如何估计RTT
SampleRTT:测量从段发出去到收到ACK时间,用这个值当做参考值
EstimatedRTT:测量多个SampleRTT,求平均值,形成RTT的估计值
使用指数加权移动平均的方法,通过新测的SampleRTT来更新原有的。
设置定时器:在测得的EstimatedRTT+一个安全的边界,如果EstimatedRTT变化大,就设置一个较大的边界。
测量RTT的变化值:SampleRTT与EStimatedRTT的差值:
定时器超时时间的设置:
2.2.发送方要处理下面三个事件:
TCP发送端程序
注释:NextSeqNum和SendBase初始化,然后进入无线循环,响应不同的事件。
第一个事件从上层收到数据(data received from applicaion above):
使用NextSeqNum创建一个TCP段
如果定时器没在运行,就将它启动
将TCP段交给网络层
更新NextSeqNum
第二个事件超时(timeout):
重传具有最小序列号的没有被确认过的段
重新启动定时器
第三个事件:收到确认序列号是y的ACK
如果y大于SendBase,更新SendBase
如果有没有被确认的segments,重新启动timer
2.3TCP重传示例:
(1)丢失ACK的场景
A发了一段序列号是92,里面有8个byte的数据,B在收到后发一个确认值序列号是100,ACK丢失,主机A发送timeout事件,A重传segment,
B收到后发送ACK,这次A收到了将SendBase更新为100。
(2)timeout设短了的情景
首先发了一个序列号为92的8个字节的段,紧接着发了一个序列号为100的8个字节的段,B两个都正确收到了,发了ACK=100和
ACK=120,因为定时设短了,序列号为92的段发送了超时时间,所以重传序列号为92的段,这之后陆续收到了ACK=100和ACK=120,
所以将SendBase先更新到100,接着更新到120,接收方收到重传的段,发送了ACK=120(TCP使用累计确认的机制,所以不是发100),
A收到了Send Base,任然是120。
(3)ACK累计确认场景
A先发了序列为92的段,接着发了序列号为100的段,B收到序列号为92的段后发送了ACK=100,传输过程中丢失,当B收到序列号
为100的段后发送了ACK=120,此时A收到后SendBase更新为120(因为TCP采用的累计确认的方式,收到ACK=120,说明序列号100
之前的都收到了)
2.4快速重传机制:
原因:TCP的实现中,如果发生超时,超时时间间隔将重新设置,即将超时时间间隔加倍,导致其很大,这样分组丢失,检测timeout
要花很长的时间。
处理机制:如果sender收到对同一数据的3个ACK,则假定该数据之后的段已经丢失,那么在定时器超时之前即进行重传。