Day7: TCP:面向连接的传输、TCP:可靠数据传输、TCP:流量控制、TCP:连接管理

加油!偷博仔

今天的看到的诗,是灰色的

天是灰色的
路是灰色的
楼是灰色的
雨是灰色的
在一片死灰之中
走过两个孩子
一个鲜红
一个淡绿
————《感觉》1980年7月


进入正题

一、 TCP:面向连接的传输

1.TCP:概述 (RFCs: 793, 1122, 1323, 2018, 2581)

在这里插入图片描述

Explanation:
·
所谓没有报文边界
发送方发两个小报文,也许接收方收到1个大的报文,或者反过来。
发送和接收缓存
为了超时重发或者检错重传,匹配Send和receive的速度不一致
·
MTU:
Maximum Transmission Unit,最大数据传输单元,网络传输最大报文包;以太网MTU最大值是1500B
MSS:
Maxitum Segment Size应用进程发给传输层TCP实体的报文段,要根据MSS的大小进行切分和加TCP头部信息,变成TCP报文段(segment)
·
所以,(Message 转换成字节流,再被划分成一个个的MSS)
MSS+TCP头部信息+IP头部信息 <= MTU(比如以太网MTU1500B),(“于是就不存在一个分片的问题?”什么分片…)
·
否则,如果要发送的IP数据报比数据链路层的MTU大,则无法发送该数据报。
还可以参考一下这位网友的分享:MSS与MTU的关系


2.TCP报文段结构

在这里插入图片描述

Make some explanation:
16bits 源端口,16bits目标端口
32 bits 序号、确认号。
所以,聪明的,同理可得:可选项32bits;校验和等等16bits
字节序号:
对于应用层交下来到Message,划分层一个个的MSS,每一个TCP报文段(segment)的body部分,就是载荷部分(对应MSS),而载荷部分第一个Byte(字节)在整个字节流的offset(偏移量) 就是字节序号

3.TCP 序号, 确认号

在这里插入图片描述

接收方处理乱序的segment 可以缓存也可以drop,没有规定。取决于…
在这里插入图片描述
Explanation:

  • Host A → Host B Seq=42, ACK=79, data = ‘C’:
    HostA,商量的初始序号是Seq = 42,并且希望Host B 初始序号从 79号开始,要求回显字节C
  • 接着Host B → Host A Seq=79, ACK=43, data = ‘C‘:
    由于此前Host B 收到了Seq42,处理完后确认ACK=43。同时ACK=43说明Host B已经收到42及以前,并且希望Host A从43开始。
    …于是就这样了

4.TCP往返延时(RTT)和超时

设置和测量/估计RTT都要得当啊。

  • Q: 怎样设置TCP超时?
     比RTT要长  但RTT是变化的
     太短:太早超时 不必要的重传
     太长: 对报文段丢失反应太慢,消极

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

TimeoutInterval是适应性的测量与计算
在这里插入图片描述
当前EstimatedRTT的计算:
`

EstimatedRTT = (1-α)EstimatedRTT + αSampleRTT” :
等号左边,是当前的均值RTT等号右边EstimatedRTT是最近之前的均值RTT, 每隔一个采样时间之前,要再×一个(1-α),给当前均值的贡献,成指数下降。
`
Estimated :adj.估计的。
在这里插入图片描述
这个DevRTT(Deviation RTT)很类似标准差,是SampleRTT和EstimatedRTT之间的偏差值/变化值
DevRTT = (1-β)DevRTT + β(|SampleRTT-EstimatedRTT|) :计算平滑RTT和真实的差距(加权移动平均)


接下来看TCP这么做RDT的

二、TCP:可靠数据传输

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

  •  管道化的报文段 (• GBN or SR )
  •  累积确认(像GBN)
  •  单个重传定时器(像GBN)
  •  是否可以接受乱序的,没有规范

通过以下事件触发重传

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

首先考虑简化的TCP发送方: (下面第1点)

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

1.TCP 发送方(简化版

我对下图的Explanation:
·
最初,建立TCP连接。从虚线开始,有一个初始化的Next序号和SendBase,
(作为开始的发送方,首先发送的字节序号都是从,初始化的序号开始发的)
·
然后就wait for event
顺时针看
于是wait到了,应用进程来了data,就创建Segment、发送窗口前沿seq。
再交到下层进行ip封装数据报和发送
发送窗口前沿滑动:NextSeqNum = NextSeqNum + length(data)
未计时,就计时开始
·
如果timeout,就只传送具有最小序号的未确段
像SR,不是将所有未确认的都传一遍
`
当ACK received,且ACK的值是y,
如果y > SendBase,那么SendBase = y
相当于发送窗口后沿向前滑动到位置y,
最后有个对定时器的操作,看图吧
在这里插入图片描述


1.1TCP发送方事件:(ppt的对上图的Explanation)

从应用层接收数据:

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

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

收到确认:

  •  如果是对尚未确认的报文段确认
  •  更新已被确认的报文序号  如果当前还有未被确认的报文段,重新启动定时器
    在这里插入图片描述

再来欣赏一下实现1.TCP发送发图片的,伪代码

	NextSeqNum = InitialSeqNum
	SendBase = InitialSeqNum
	loop (forever) {
    
    
		switch(event) 
		event: data received from application above 
			create TCP segment with sequence number NextSeqNum 
			if (timer currently not running) 
				start timer 
			pass segment to IP 
			NextSeqNum = NextSeqNum + length(data) 
		event: timer timeout
			retransmit not-yet-acknowledged segment with smallest sequence number start timer 
		event: ACK received, with ACK field value of y 
			if (y > SendBase) {
    
     
				SendBase = y
			if (there are currently not-yet-acknowledged segments) 
				start timer 
				} 
	} /* end of loop forever */
	
	/*注释:• SendBase-1: 最后一个累积确认的字节例:
			• SendBase-1 = 71;
			y= 73, 因此接收方期望73+ ;
			y > SendBase,因此新的数据被确认
 	*/

最后再来一张图
对顺序收到的最高字节确认;
在这里插入图片描述


2.产生TCP ACK的建议 [RFC 1122, RFC 2581]

在这里插入图片描述

3.快速重传

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


 通过重复的ACK来检测报文段丢失

  •  发送方通常连续发送大量报文段
  •  如果报文段丢失,通常会引起(收到)多个重复的ACK

 如果发送方收到同一数据的3个冗余ACK,(如下图三个冗余ACK50),

  • 重传最小序号的段:
  • 它假设跟在被确认的数据后面的数据丢失了

在这里插入图片描述
在这里插入图片描述
• 第一个ACK是正常的;
• 收到第二个该段的ACK,表示接收方收到一个该段后的乱序段;
• 收到第3,4个该段的ack,表示接收方收到该段之后的2个 ,3个乱序段,可能性非常大
段丢失了

3.1快速重传算法:

在这里插入图片描述

dup :duplicate :adj.完全一样的、冗余的

三、TCP:流量控制

接收方控制发送方,
不让发送方发送的太多、太快
防止让接收方的缓冲区溢出

在这里插入图片描述
TCP套接字的接收缓冲区:TCP socket receiver buffers
在这里插入图片描述

然后TCP是全双工的,于是:

  •  接收方在其向发送方的TCP段头部的rwnd字段“通告”其空闲buffer大小
    (不是单独发一个确认信息,而是在“寄快递的盒子上做了个小标注free buffer space”)
    • RcvBuffer大小通过socket选项设置 (典型默认大小为4096 字节)
    •  很多操作系统自动调整RcvBuffer
  • 发送方限制未确认(“in-flight”)字节的个数 接收方发送过来的 rwnd 值
    保证接收方不会被淹没

回顾一下接收窗口和接收缓冲区(Receive Window && Receive Buffer field)
在这里插入图片描述


四、TCP:连接管理

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

  •  同意建立连接(每一方都知道对方愿意建立连接)
  •  同意连接参数
    在这里插入图片描述

1.同意建立连接

在这里插入图片描述

2次握手的失败场景:
半连接,
左边客户主机进程,由于acc_conn(x)超时,重传了新的连接请求(req_conn(x)),
导致服务器主机进程维护了一个半连接
在这里插入图片描述

2.TCP 3次握手 (2次握手解决方案)

TCP中有个标志位SYN。
SYN = 1 代表连接请求
Seq = x 代表从x字节开始传
在这里插入图片描述

一般第一次数据传递和第三次握手是一起的。

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

在这里插入图片描述

采用初始化序号作为TCP段的序号,而不采用固定的序号
就可以
有效避免
老的连接的数据

新的连接的数据
造成干扰

2.2三次握手: FSM(Finite State Machine)

寄几看看叭~
在这里插入图片描述

3.TCP: 关闭连接

  • 客户端,服务器分别关闭它自己这一侧的连接 (两个方向的连接单独拆除)
     发送FIN bit = 1的TCP段 (FIN = 1表示关闭连接,)
  • 一旦接收到FIN,用ACK回应
     接到FIN段,ACK可以和它自己发出的FIN段一起发送
  • 可以处理同时的FIN交换

有些好玩的事情,
要是FIN的确认没收到咋搞,?
要是FIN根本没法过去咋搞,?
要是有人伪造FIN发送给对方咋搞,?
哈哈哈

TCP连接的释放,并不完美,采用了计时器的机制来断开连接。
在这里插入图片描述


本篇结束

猜你喜欢

转载自blog.csdn.net/m0_46156900/article/details/113826344