具体的运输层协议---UDP和TCP

概述

前面我们总体介绍了运输层协议的作用(参考我的另一篇文章运输层协议概述),知道了运输层仅在端系统中工作,而不出现在中间网络元素中(如路由器等),现在我们来具体看两种运输层协议TCP协议UDP协议

TCP协议

TCP协议概述

TCP是一种面向连接的、可靠数据传输的、具有拥塞控制机制的运输层协议(这三个特点我们稍后一一解释),既然是运输层协议,那么它的职责就是:在发送主机中,TCP将来自应用程序的报文移动到网络层;在目的主机中,TCP将来自网络层的报文段交付给在主机上运行的适当应用程序进程

  • TCP是全双工服务,即在两台主机之间建立TCP连接后,某一台主机既可以作为发送方,也可以作为接收方
  • TCP报文的格式(我们通过TCP报文格式来深入了解TCP协议的种种特性,牢记这幅图中不同字段的颜色!!!)
    在这里插入图片描述
  • 浅蓝色部分用于多路分解和多路复用(不明白可参考运输层协议概述
    源端口号(16bit)
    目的端口号(16bit)
  • 橙色首部长度字段(4bit),用于指示TCP报文除应用层数据以外的长度
  • 白棕色选项字段(变长且可有可无),该字段用于发送方与接收方协商最大报文段长度 (MSS) 时,或在高速网络环境下用作窗口调节因子时使用
  • 深蓝色部分用于处理发送方的紧急数据,当发送端生成的TCP报文中的应用层数据中包含紧急数据时,URG(1bit)字段置1,紧急数据指针(16bit)指向紧急数据。针对紧急数据,PSH(1bit)应置1,表示接收方应立即将数据交给上层
  • 灰白色部分为保留字段(6bit),没有使用

紫色部分、粉红色部分和浅绿色部分稍后详细解释,先简单看一下

  • 粉红色部分用于TCP连接的创建与断开
    RST(1bit)、SYN(1bit)、FIN(1bit)
  • 紫色部分用于可靠数据传输
    序号(32bit)、确认号(32bit)、ACK(1bit)
  • 浅绿色部分用于流量控制,该字段用于指示接收方愿意接受的字节数量
    接收窗口(16bit)

TCP协议的可靠数据传输(可靠性)

在了解这部分之前应该先了解一下可靠数据传输原理(不了解的兄弟可以参考一下这篇文章),了解了原理就可以很快理解为什么要使用序号和确认号字段

TCP协议的可靠性总的来说就是要保证数据要无差错、无损失且有序地从发送方到接收方,我们知道网络层地IP协议是不可靠的,因此如果TCP协议必须通过一些机制来保证数据传输地可靠性

  • 首先解释一下紫色部分的字段
    序号(32bit):一个报文段序号是该报文段中包含的应用数据的首字节的字节流编号
    在这里插入图片描述
    确认号(32bit):主机A和主机B通信通过TCP协议进行通信,假设主机A将要发送的第一个TCP报文的序号为48,主机B将要发送的第一个TCP报文的序号为72,且假设每个TCP报文的应用层数据长度为8字节。主机A首先向主机B发送一个序号为48,确认号为72的报文(因为主机A希望主机B向它响应一个序号为72的报文),由于每个TCP报文的应用层数据长度为8字节,所以主机B向主机A响应一个序号为72,确认号为56(48+8,表示主机B希望主机A向它响应一个序号为56的报文)的报文,以此类推。
    ACK字段(1bit):指示确认字段中的值是有效的,即该报文段包括一个对已被成功接收报文段的确认
  • 我们结合TCP报文图中的紫色部分字段来看TCP的可靠性实现
    在这里插入图片描述
  • 从状态图可以看出来TCP的可靠数据传输相当于GBN协议和SR协议参考可靠数据传输原理)的结合
  • 考虑一下重传超时间隔设置为多少比较合适
  • 显然,超时间隔必须大于该连接的往返时间 (RTT) ,即从一个报文段发出到它被确认的时间,那么RTT又是如何确定的呢?
    其实,大多数 TCP的实现仅在某个时刻做一次 SampleRTT(样本RTT) 测量,而不是为每个发送的报文段测量一个 SampleRTT,每测一个新的SampleRTT就和之前的值取加权平均值EstimatedRTT
    EstimatedRTT = (1 -α) * EstimatedRTT +α*SampleRTT α=0.125(参考值)
    这个加权平均对最近的样本赋予的权值要大于对老样本赋予的权值。这是
    很自然的,因为越近的样本越能更好地反映网络的当前拥塞情况
  • SampleRTT偏离 EstimatedRTT 的程度:
    DevRTT = (1 -β) *DevRTT +β*|SampleRTT - EstimatedRTT| β=0.25(推荐值)
  • 当EstimatedRTT和DevRTT已知时
    重传超时间隔应为TimeoutInterval = EstlmatedRTT+4 * DevRTT
    初始值推荐1s
    当出现超时后,TimeoutInterval值将加倍,以免即将被确认的后继报文段过早出现超时。
    一旦报文段收到并更新 EstimatedRTT后,TimeoutInterval 就又使用上述公式计算了

三次握手与四次挥手(TCP连接的创建与断开)

  • 首先我们思考为什么会有三次握手与四次挥手?
    因为规定TCP协议是一个面向连接的协议,所谓面向连接就是在客户向服务器发送应用层数据之前,应该先向服务器发送特殊报文段,经过客户机和服务器的几次响应,从而分别在客户机和服务器上为该连接分配必需的缓存和变量

  • 我们结合TCP报文图中粉红色部分(RST、SYN、FIN字段)来了解TCP连接的创建与断开
  • TCP连接的创建(三次握手
    在这里插入图片描述
    如果对图中的seq(序号)和ack(确认号)不理解的可以参考上文对这两个字段的解释
  • 我们简单说一下三次握手的过程
    ①客户端的TCP首先向服务器端的TCP发送一个SYN字段为1的报文段,该报文段中不包含应用层数据,该报文段会被封装在IP数据报中,并发送给服务器
    ②一旦包含TCP SYN报文段的数据报到达服务器主机,服务器会从该数据报中提取出 TCP SYN 报文段,为该 TCP 连接分配 TCP缓存和变量,并向该客户 TCP 发送允许连接的报文段(SYNACK报文段),SYNACK报文段也不包含应用层数据
    ③在客户端收到SYNACK报文段后,客户机也要为该TCP连接分配缓存和变量,最后客户机TCP向服务器TCP发送一个对服务器的允许连接报文段的确认报文段(SYN=0,因为连接已经建立),这个报文段中可以携带应用层数据
  • 为什么是三次握手而不是两次握手?!!!!
    在此我仅发表个人观点,如有错误,欢迎碰撞
    首先我们明确一点,TCP协议是一种可靠数据传输协议,由可靠数据传输原理可以知道 要实现可靠数据传输协议就必须引入序号和确认号字段 ,又因为TCP协议是全双工服务,因此为了维护TCP的可靠数据传输,必须经过三次握手来使通信双方互相告知起始序列号,并且确认对方已经收到了起始序列号。
    如果只有两次握手,只有连接发起方的初始序列号能得到确认,而被连接方的初始序列号得不到确认(如果只有两次握手,在第二次握手之后便会认为TCP连接建立成功。而连接建立成功时,被连接方的初始序列号还没有得到确认,这样是不能保证可靠数据传输的,必须通过第三次握手对被连接方的初始序列号进行确认)。
  • TCP连接的断开(四次挥手
    在这里插入图片描述
  • 为什么需要四次挥手?
    因为TCP是全双工服务,第二次挥手完毕之后表示客户机不在向服务器发送数据,但是还可以接受来自服务器端的数据。等服务器端剩余的数据发送完毕后再进行第三次挥手,因此第二次挥手和第三次挥手不能合并。共需要四次挥手。
  • 为什么需要定时等待?
    因为第四次挥手的ACK报文可能丢失,客户机会在等待的过程中可以重传ACK报文。

TCP的流量控制和拥塞控制

TCP的流量控制

一条 TCP连接的每侧主机都为该连接设置了接收缓存,如果某应用程序读取数据时相对缓慢,而发送方发送得太多、太快,发送的数据就会很容易地使该连接的接收缓存溢出,因此我们必须引入流量控制机制

  • TCP报文图中浅绿色部分用于流量控制,该字段用于指示接收方愿意接受的字节数量
    接收窗口(16bit):用于给发送方一个指示——该接收方还有多少可用的缓存空间
  • 假设主机A通过一条TCP连接向主机B发送一个大文件
    LastByteRead: 主机B上的应用进程从缓存读出的数据流的最后一个字节的编号
    LastByteRcvd: 从网络中到达的并且已放人主机B接收缓存中的数据流的最后一个字节的编号
    RcvBuffer:表示主机B接收缓存的大小
    由于TCP不允许缓存溢出,所以LastByteRcvd - LastByteRead <= RcvBuffer
    接收窗口的大小
    rwnd=RcvBuffer - [LastByteRcvd - LastByteRead ]
  • 主机B通过接收窗口字段将rwnd发送给主机A,首次发送rwnd=RcvBuffer
  • 主机A接收到rwnd并跟踪变量LastByteSent(最后一个被发送的报文序号)和LastByteAcked(最后一个被确认的报文序号)
    LastByteSent-LastByteAcked表示主机A发送了但未被确认的数据量。
    只要保证LastByteSent-LastByteAcked <= rwnd,就可以保证主机A不会使主机B的接收缓存溢出(主机A和主机B调换身份也是一样的道理)
  • 考虑一个问题,假设主机B的缓存已满,并且假设主机B没有任何数据要发送给主机A。此时,主机B上的应用进程将接收缓存清空,主机A也不会知道,这样主机A就会被阻塞
    为了解决这个问题,TCP规定,当主机B的接收窗口为0时,主机A继续发送只有一个字节数据的报文段。这些报文段将会被接收方确认。最终缓存将开始清空,并且确认报文里将包含一个非0的rwnd值,这样就解除了对主机A的阻塞

TCP的拥塞控制

TCP拥塞控制是指发送方到接收方之间的路径有拥塞时,适当降低发送方的发送速率,发送方与接收方之间的路径无拥塞时,适当提高发送方的发送速率

  • 一个 TCP 发送方如何限制它向其连接发送流量的速率呢?
    运行在发送方的TCP拥塞机制跟踪一个额外的变量cwnd(拥塞窗口
    要保证LastByteSent-LastByteAcked <= {rwnd,cwnd}
    这样就限制了发送方未确认的数据量,从而间接约束了发送方发送速率
  • TCP发送方如何感知到目的地的路径上存在拥塞呢?
    当出现过度的拥塞时,在沿着这条路径上的一台(或多台)路由器的缓存会溢出,引起一个数据报(包含一个 TCP 报文段)被丢弃,丢弃的数据报接着会引起发送方的丢包事件(要么超时或收到3个冗余 ACK) ,发送方就认为在发
    送方到接收方的路径上出现了拥塞的指示
  • 当发送方感受到端与端存在拥塞时,采用何种算法来改变其发送速率呢?
    在这里插入图片描述

UDP协议

UDP协议是一种无连接、不可靠的运输层协议。无连接就是不需要进行TCP协议中的三次握手和四次挥手,不可靠就是没有类似于TCP协议中的可靠数据传输机制。

  • UDP报文段格式
    在这里插入图片描述
  • 既然UDP不可靠为什么还要使用UDP?
    ①采用 UDP 时,只要应用进程将数据传递给 UDP UDP 就会将此数据打包进 UDP 报文段井立即将其传递给网络层。实时程序有这样的需求(如因特网电话、实时视频会议)
    ②无需建立连接,不需要进行三次握手,不会引入建立连接的时延。DNS采用UDP
    ③不需要端系统来维护一些状态信息(如接收和发送缓存、拥塞控制参数),某些专门用于某种特定应用的服务器当应用程序运行在 UDP 之上而不是运行在 TCP 上时,一般都能支持更多的活跃客户
    ④分组首部开销小,TCP报文段有20字节的首部开销,UDP数据报只有8字节的首部开销
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值