• 为什么说TCP协议是可靠的


    问题背景

    • 日常面试时,几乎所有学过计算机的都知道,TCP协议是可靠的,UDP协议不可靠的。为什么TCP协议是可靠的?它用什么机制保证可靠呢?

    提出问题

    1. 由于IP 数据包的 MTU 有长度限制, TCP报文段过大时,需要切割。切割之后发送出去,由于网络链路的不确定性,接收端接收到包的次序和发送次序很大概率是不一致的。接收端如何把接收到的“同一批”TCP报文段数据拼接成预期的二进制数据?
    2. 发送方发送了一个TCP报文,怎么样确认接收方接收到了这个报文?
    3. 发送方发送了一个TCP报文,接收端如何保证接收到的报文段的数据没有在途中被“其他人”篡改?

    TCP协议的初级解决方案

    1. 采用序列号标识一个TCP报文

      • TCP报文段头部的,有一个字段是序列号(Sequence)
      • 接收端可以使用sequence对不同的TCP报文进行排序和拼接
    2. 初级解决方案: ACK机制+确认号

      • 接收方接收到序号为seq的TCP报文之后,期望接收到序列号为seq+1的TCP报文,确认号会填充seq+1
      • ACK位会置为1,表示确认接收到TCP报文
      • 超时未接收到ACK的情况下,发送端默认认为TCP报文段丢失,再次重发
    3. TCP报文头部字段检验和,检验报文段数据的checksum是否和接收到实际的报文段数据的checksum一致。不一致则丢弃

    初级解决方案的问题

    对于问题2的初级解决方案:存在两个问题
    1.效率低的问题。
    发送方保持发送 -> 等待ACK -> 发送 -> 等待ACK…的单线工作方式,这样的工作方式叫做 stop-and-wait。stop-and-wait 虽然实现了 TCP 通信的可靠性,但同时牺牲了网络通信的效率。同时,在等待ACK的时间段内,网络都处于闲置(idle)状态

    2.有点小缺陷
    如果当前的TCP报文段一直没有被确认,会导致后续的片段无法发送出去。

    TCP协议的优化方案

    • 滑动窗口机制
      • 不展开,可查看参考链接中的图片序列,非常详细
      • TCP报文段首部带有一个窗口
      • 接收端减少了 ACK 回复所消耗的流量,因为采用的是累计 ACK 回复
      • 发送端在大多数情况下不会因为单个TCP报文段没有接收到ACK而被阻塞继续发送
      • seq和确认号的一个细节
        • 接收到接收到序列号为seq的TCP报文之后,发送的ACK报文的确认号不一定是seq+1,可能是seq+n(n-1是接收到序列号为seq的TCP报文段之前已经接收到的TCP报文段的个数)

    总结

    • TCP协议可靠使用以下机制来保证

      • TCP报文段首部sequence字段唯一标识TCP报文段,也作为顺序的标识
      • TCP通信采用ACK+确认号的确认机制
      • TCP报文首部的checksum字段记录报文段数据的checksum
    • TCP协议的优化

      • 采用滑动窗口机制,提升通信效率

    参考资料

  • 相关阅读:
    PHP 数据库连接
    php函数
    php数组基础
    Jquery元素追加和删除
    jquery获取父,同,子级元素
    深入理解css中position属性及z-index属性
    php运算符
    MySQL主键与索引的区别和联系
    php 常量
    20150408--Sphinx+邮件激活-02
  • 原文地址:https://www.cnblogs.com/HelloGreen/p/11747269.html
Copyright © 2020-2023  润新知