前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面向数据连接:TCP

面向数据连接:TCP

作者头像
用户11097514
发布2024-05-31 12:28:09
980
发布2024-05-31 12:28:09
举报
文章被收录于专栏:技术分享

面向连接的传输: TCP

TCP:概述

  • 提供的是点对点的服务: 一个发送方,一个接收方
  • 可靠的、按顺序的字节流 : 没有报文边界
  • 管道化(流水线): TCP拥塞控制和流量控制设置 窗口大小
  • 发送和接收:
img
img
  • 全双工数据 : 在同一连接中数据流双向流动 ,两者可以互相发 ( ==MSS:最大报文段大小 [任意一个网络都有它最大的传输部分,如果应用交互的报文非常长的话,就必须打成一个个MSS的大小。每层都要加上头部信息==])
  • 面向连接: 在数据交换之前,通过握手(交换控制报文) 初始化发送方、接收方的状态 变量
  • 有流量控制: 发送方不会淹没接收方

段结构

TCP报文段结构

img
img

源端口号:16bit

目标端口号: 16bit

序号: 32bit

TCP序号,确认号:

序号:

  • 报文段首字节 的在字节流的编号

如果初始序号为X, 那么第n个序号就是X + n*MSS 序号具体就是: 上层交互的报文 ,我们按照MSS为单位,切割成为一个个的MSS报文段。 每个TCP都有头部和Body部分, Body部分就是MSS的载荷部分。载荷部分(Body)中的第一个字节就是MSS在整个报文中的偏移量.

确认号:

  • 期望从另一方收到的下一个字节的序号
  • 累积确认

发送方发送, 接收方接收, 假设接收方发送了ACK为555, 那么就说明接收方接收到了554及其之前的所有字节。而且期望发送方从556的序号开始发送

首部长度:

  • 4bit

保留未用:不太清楚

标志位: UAPRSF

接收窗口 : 用于流量控制。 (如果接收窗口为 X, 那么就表示能接收 Xbit的数据)

紧急指针: 不怎么用。

img
img
img
img

TCP面临的通信场景(往返延时(RTT)和超时 )

采用自适应的策略和计算。

  1. 怎样设置TCP 超时?

如果比RTT要长 , 但RTT是变化的 如果太短:太早超时 会产生不必要的重传 如果太长:对报文段丢失 反应太慢,消极

  1. 怎样估计RTT?

SampleRTT:测量从报文段发出到 收到确认的时间 如果有重传,忽略此次测量 SampleRTT会变化,因此估计的 RTT应该比较平滑 对几个最近的测量值求平均,而 不是仅用当前的SampleRTT

  1. EStimatedRTT(估计的往返延迟时间)的计算:

EstimatedRTT = (1- a)*EstimatedRTT + a*SampleRTT

  • 指数加权移动平均
  • 过去样本的影响呈指数衰减
  • 推荐值:a = 0.125

往返延迟时间分布:

img
img

设置超时

平均值越大, 我们设置的超时时间就需要变大 往返延迟的变化越大, 就会越分散 , 超时时间就需要设置的越大。

EstimtedRTT + 安全边界时间

  • EstimatedRTT变化大 (方差大 ) -> 较大的安全边界时间

SampleRTT会偏离EstimatedRTT多远:

img
img

当前的采样值, 离偏差程度的一个平均值。

可靠数据传输(TCP怎么实现RDT)

我们知道IP提供的是不可靠的服务 ,而TCP向上层提供的确是可靠的服务, 那么这是如何实现的呢 ?

TCP在IP不可靠服务的基础上 建立了rdt

  • 管道化的报文段 • GBN or SR (它实现了两者的混合体)
  • 累积确认(像GBN)
  • 单个超时重传定时器(像GBN)
  • 是否可以接受乱序的,没有规范

通过以下事件触发重传

  • 超时(只重发那个最早的未确认 段:SR)
  • 重复的确认 ( 例子:收到了ACK50,之后又收到3 个ACK50 )

首先考虑简化的TCP发 送方:

  • 忽略重复的确认
  • 忽略流量控制和拥塞控 制

TCP 发送方(简化版)

img
img

TCP发送方事件:

从应用层接收数据:

  • 用nextseq创建报文段
  • 序号nextseq为报文段首字 节的字节流编号
  • 如果还没有运行,启动定 时器
    • 定时器与最早未确认的报文 段关联
    • 过期间隔: TimeOutInterval

超时:

  • 重传后沿最老的报文段
  • 重新启动定时器

收到确认:

  • 如果是对尚未确认的报 文段确认
    • 更新已被确认的报文序号
    • 如果当前还有未被确认的 报文段,重新启动定时器
img
img

ACK7: 表示7之前的都发送了并且已经得到了确认。接下来就需要从8号开始

TCP: 重传

img
img
img
img

产生TCP ACK的情况及其 建议

接收方的事件

TCP接收方的动作

所期望序号的报文段按序到达。 所有在期望序号之前的数据都 已经被确认

延迟的ACK。对另一个按序报文段的到达最 多等待500ms。如果下一个报文段在这个时 间间隔内没有到达,则发送一个ACK。

有期望序号的报文段到达。 另一个按序报文段等待发送ACK (一次到两个报文)

立即发送单个累积ACK,以确认两个按序报 文段。

比期望序号大的报文段乱序到达。 检测出数据流中的间隔

立即发送重复的ACK,指明下一个期待字节 的序号

能部分或完全填充接收数据间隔 的报文段到达。

若该报文段起始于间隔(gap)的低端, 则立即发送ACK。

快速重传

就是在快速定时器超时之前已经收到了某个段的冗余ACK, 那么就需要在某个段还没有到时的情况下,将这个段快速重新传出去 ,而不是等待它超时了再进行重传。

  • 超时周期往往太长:
    • 在重传丢失报文段之前的 延时太长
  • 通过重复的ACK来检测 报文段丢失
    • 发送方通常连续发送大量 报文段
    • 如果报文段丢失,通常会 引起多个重复的ACK

如果发送方收到同一数据 的3个冗余ACK,重传最 小序号的段:

==快速重传:在定时器过时 之前重发报文段==

它假设跟在被确认的数据 后面的数据丢失了 • 第一个ACK是正常的; • 收到第二个该段的ACK,表 示接收方收到一个该段后的 乱序段; • 收到第3,4个该段的ack,表 示接收方收到该段之后的2个 ,3个乱序段,可能性非常大 段丢失了

img
img

快速重传算法:

代码语言:javascript
复制
event: ACK received, with ACK field value of y
    if (y > SendBase) {
    SendBase = y
    if (there are currently not-yet-acknowledged segments)
    	start timer
	}	
else {  //已确认报文段的一个重复确认
    increment count of dup ACKs received for y
    if (count of dup ACKs received for y = 3) { //快速重传
    	resend segment with sequence number y
}

流量控制

目的就是防止发送方发送的太快, 而使得接收方得缓冲区溢出。

img
img
  • 接收方在其向发送方的TCP段 头部的rwnd字段“通告”其空 闲buffer大小
    • RcvBuffer大小通过socket选项 设置 (典型默认大小为4096 字 节)
    • 很多操作系统自动调整 RcvBuffer
  • 发送方限制未确认(“inflight”)字节的个数≤接收 方发送过来的 rwnd 值
  • 保证接收方不会被淹没
img
img

TCP流量控制

相当于木桶效应, 即使发送方能够发送4096bit得数据。 但是接收方只能接收1080bit的数据, 那么发送方也只能有效发出1080bit的数据。

img
img

连接管理

连接的本质:

  1. ==双方都知道要和对方通信==
  2. ==双方要为通信连接准备好必要的资源(初始序号等)==
  3. ==控制变量需要做置位(序号、初始化receiveBuffer(接收窗口)大小等都需要告诉对方)==*

在正式交换数据之前,发送方和接收方握手建立通信关系:

  • 同意建立连接(每一方都知道对方愿意建立连接)
  • 同意连接参数

为连接做 准备

img
img

两次握手建立连接的不可行性

img
img
  1. 变化的延迟(连接请求的段 没有丢,但可能超时)
  2. 由于丢失造成的重传 (e.g. req_conn(x))
  3. 报文乱序
  4. 相互看不到对方

2次握手失败的场景:

img
img

Client发送了建立连接的请求, 然后Server收到连接请求, 并且进行了确认, 然后发送给了Client 。Client接收到了Server的连接确认, 表示Client知道Server是活跃的, 但是之后Client并没有继续发送确认信息。 因为握手已经结束, 所以Server并不知道你Client是否活跃,所以这就是所谓的半连接。

TCP 三次握手

基于2次握手的不可行性, 我们通过三次握手来实现解决。 基本方案是 : 变化的初始序号+双方确认对方的序号(3次握手)

img
img
  1. Client建立起连接 。然后将自己的初始序号, x发送TCP SYN报文。

SYN = 1 就是连接请求, Seq = x 就是告诉对方,我将要从x这个字节开始传输。(x就是初始序号)

  1. Server接收到连接请求 ,发出连接确认。

SYN = 1 表示连接请求, Seq = y 就是告诉Client我要从y这个字节开始传输(y就是server的初始序号)

ACK =1 表示我确认接收到了连接请求,ACKNum 表示我确认接收到了x的请求 ,希望你下次从x+1开始传输

  1. Client接收到了第二次握手的信号,发出第三次握手

接收到SYN = 1 表示Server是活跃的, 发送SYNACK 的ACK表示 该报文可能包含C-S的数据

接收到了Server的初始序号Seq = y, 本次我就要确认Server给的初始序号。

并且发送ACK = 1表示Client确认了这次的请求。ACKNum = y+1 表示我确认接收到了y的请求 ,希望你下次从y+1开始传输

  1. Server接收到Client的确认请求。

ACK(y)表示Client是活跃的。

通常第三次握手跟第一次的数据传递是放在一块的。

3次握手解决:半连接和接收老数据问题

img
img

因为三次握手首先需要将初始序号(x)告诉对方, 然后收到对方的确认之后, 再进行后续的传输,如果说client本次传输的序号不是(x+1) 那么Server就会refuse。 就不会出现老数据传输

TCP 三次握手 : FSM

img
img

TCP: 关闭连接

  1. 客户端,服务器分别关闭它自己这一侧的连接【通过发送FIN bit = 1的TCP段 】
  2. 一旦接收到FIN,用ACK回应 【 接到FIN段,ACK可以和它自己发出的FIN段一起发 送
  3. 可以处理同时的FIN交换
img
img
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-08-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 面向连接的传输: TCP
    • TCP:概述
      • 段结构
        • TCP序号,确认号:
        • TCP面临的通信场景(往返延时(RTT)和超时 )
      • 可靠数据传输(TCP怎么实现RDT)
        • TCP 发送方(简化版)
        • TCP发送方事件:
        • TCP: 重传
        • 产生TCP ACK的情况及其 建议
        • 快速重传
      • 流量控制
        • TCP流量控制
      • 连接管理
        • 两次握手建立连接的不可行性
        • TCP 三次握手
        • 3次握手解决:半连接和接收老数据问题
        • TCP 三次握手 : FSM
        • TCP: 关闭连接
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档