读完《计算机网络自顶向下设计方法》第三章可靠数据传输的原理,有些明白为什么TCP报文要这样设计。
第一种情况:仅考虑通信信道上不会丢包,只会有比特差错产生。
通过校验和机制(checksum)和重传机制,在双方保证数据包可靠性。发送方/接收方状态机如下所示。
数据包发送后,发送方等待接收方的NAK(否定)/ACK(肯定)数据包。如果接收方返回NAK,那么说明数据包在传输过程中产生比特差错,发送方重新发送数据包;如果收到ACK,说明数据包成功被接收。
接收方接收数据包,查看checksum。如果数据包校验和成功,那么将数据包数据取出,构造ACK数据包给发送方;否则构造NAK数据包给发送方。
接收方与发送方通过checksum和NAK/ACK完成数据的可靠传递。但是这里面有个问题:如果NAK/ACK数据包在传输时发生比特差错,该如何处理?
需要采用新的办法:序号(sequence number),接收方只需要检查序号即可确认收到的数据包是否是一次重传。如果接收到的ACK/NAK数据包校验和失败,那么将刚才的数据包重传。接收方收到重传的数据包后,检查其序号与原来的一致(与期望的不一致),那么再次发送ACK/NAK。
需要2个序号即可满足重传的场景,状态机如下所示:
发送方发送序号为0的数据包,如果接收到NAK且校验和成功,那么与上面处理类似,重传数据包。如果接收的数据包校验和失败,说明ACK/NAK在传输中出现比特差错,重传数据包。
接收方收到序号为0的数据包后,校验和成功,发送ACK数据包,并且期待下一个序号为1的数据包。如果下一个数据包序号为0,那么说明ACK传输过程中出现比特差错,那么再次发送ACK数据包。
通过checksum/ACK/NAK/Sequence number即可保证比特位差错情况下的可靠数据传输。
通过冗余ACK技术,可以简化上面的流程。冗余ACK:即不发送NAK而发送上个数据包的ACK,发送方收到对同一个数据包的两个ACK后,就知道接收方没有收到其后面的数据包。简化后的状态机如下图所示。
发送方:
接收方: