TCP协议详解

文章目录

  • 前言
  • 一、TCP协议概述
    • 1.协议特点
    • 2.TCP报文段
  • 二、TCP可靠数据传输
    • 1.概述
    • 2.超时重传时间选择
    • 3.快速重传机制
  • 三、TCP流量控制
  • 四、TCP连接管理
    • 1.连接建立 --- 三次握手
    • 2.连接释放 --- 四次挥手
  • 五、TCP拥塞控制
    • 1.基本原理
    • 2.慢启动(SS)
    • 3.加性增—乘性减(AIMD)
  • 总结


前言


提示:以下是本篇文章正文内容

一、TCP协议概述

1.协议特点

(1)TCP是面向连接(虚连接)的传输层协议

通信双方在发送数据之前必须建立连接,连接状态只在连接的两端中维护,在沿途节点中并不维护状态

TCP连接包括:两台主机上的缓存、连接状态变量、socket等

(2)每条TCP连接只能有两个端点,每条TCP连接只能是点对点的

这里TCP连接的端点不是主机,不是主机的IP,也不是应用进程和运输层的协议端口,TCP连接的端口是套接字(Socket) 【套接字 =(IP地址:端口号)】

每一条TCP连接唯一地被通信两端的两个端点(即两个套接字)所确定

(3)TCP提供可靠交付的服务,无差错,不丢失,不重复,按序到达(可靠有序,不丢不重)

(4)TCP提供全双工通信

同一连接中能够传输双向数据流,拥有发送缓存和接收缓存
发送缓存:准备发送的数据和已经发送但尚未收到确认的数据
接收缓存:按序到达但尚未被接收应用程序读取的数据和不按序到达的数据
在这里插入图片描述

(5)TCP面向字节流

TCP把应用程序交下来的数据仅看成是一连串的无结构的字节流
(UDP是面向数据报的)

(5)流水线机制

TCP拥塞控制和流量控制机制设置窗口尺寸

(6)流量控制机制

2.TCP报文段

TCP传送的数据单元称为报文段, 一个TCP报文段分为TCP首部TCP数据两部分,整个TCP报文段作为IP数据报的数据部分封装在IP数据报中,其首部的前20B是固定的。

TCP报文段的首部最短为20B,后面有4N字节是根据需要而增加的选项,通常长度为4B的整数倍

TCP报文段既可以用来运载数据,又可以用来建立连接、释放连接和应答

在这里插入图片描述
(1)源端口和目的端口字段: 各占2B, 端口是运输层与应用层的服务接口,运输层的复用和分用功能都要通过端口实现

(2)序号字段:占4B,TCP是面向字节流的(即TCP传送时是逐个字节传送的),所以TCP连接传送的数据流中的每个字节都编上一个序号,序号字段的值指的是本报文段所发送的数据的第一个字节的序号,建立TCP连接时,双方随机选择序列号

(3)确认号字段:占4B, 是期望收到对方的下一个报文段的数据的第一个字节的序号若确认号为N,则表明到序号N- 1为止的所有数据都已正确收到

(4)首部长度(数据偏移):占4位,这里不是IP数据报分片的那个数据偏移,而是表示首部长度,它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远

(5)保留字段

(6)紧急位URG:URG= 1时,表明紧急指针字段有效,它告诉系统报文段中有紧急数据,应尽快传送(相当于高优先级的数据), 但URG需要和紧急指针配套使用,即数据从第一个字节到紧急指针所指字节就是紧急数据

(7)确认位ACK:只有当ACK= 1时确认号字段才有效;当ACK=0时,确认号无效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置1

累计确认:该序列号之前的所有字节均已被正确接收到

序列号和ACK传输示例:
在这里插入图片描述
主机A需要序列号为79的数据,发送TCP报文数据第一个字节的序列号为42,需要数据为’C’, 主机B发送数据’C’,和数据的第一个字节的序列号,ACK=43,说明前42个字节都收到,然后主机A在回复。

(8)推送位PSH (Push): 接收TCP收到PSH= 1的报文段,就尽快地交付给接收应用进程而不再等到整个缓存都填满后再向上交付

(9)复位位RST (Reset):当 RST=1时,表明TCP连接中出现严重差错,如主机崩溃,必须释放连接,然后再重新建立运输连接

(10)同步位SYN: 同步SYN= 1表示这是一个连接请求或连接接收报文
当SYN=1, ACK=0时,表明这是一个连接请求报文,对方若同意建立连接,则在响应报文中使用SYN=1, ACK=1,即SYN= 1表示这是一个连接请求或连接接收报文

(11)终止位FIN (Finish): 用来释放一个连接,FIN= 1表明此报文段的发送方的数据已发送完毕,并要求释放传输连接

(12)窗口字段它指出现在允许对方发送的数据量,接收方的数据缓存空间是有限的,因此用窗口值作为接收方让发送方设置其发送窗口的依据,单位为字节,一般用来限制发送方发送数据的

假设假设确认号是701,窗口字段是1000,这表明,从701号算起,发送此报文段的接收方方还有接收1000B数据(字节序号为701 ~1700)的接收缓存空间

(13)校验和:和UDP校验和一样的

(14)紧急指针字段:指出在本报文段中紧急数据共有多少字节,紧急数据放在本报文段数据的最前面

(15)选项字段

(16)填充字段

二、TCP可靠数据传输

1.概述

(1)TCP在IP层提供的不可靠服务基础上实现可靠数据传输服务

(2)流水线机制(滑动窗口协议)
滑动窗口协议–>GBN,SR

(3)累积确认

(4)TCP使用单一重传定时器

(5)触发重传的事件 : 超时 或者 收到重复ACK

(6)渐进式:流量控制,拥塞控制,重复ACK

这里前面大部分已经说过来,主要讲TCP超时重传时间的选择,后面会讲渐进式

2.超时重传时间选择

TCP的发送方在规定的时间内没有收到确认就要重传已经发送的报文,超时重传难点在于如何设置定时器的超时时间?

TCP采用了一种自适应算法,它记录一个报文段发出的时间,以及收到相应的确认的时间, 这两个时间之差就是报文段的往返时间RTT

加权平均往返时间

SampleRTT: 测量从段发出去到收到ACK的时间(忽略重传)
测量多个SampleRTT,求平均值,形成RTT的估计值EstimatedRTT
在这里插入图片描述

定时器设置的超时重传时间RTO(Retransmission Time-Out)应该稍微大于估计值EstimatedRTT

定时器超时时间的设置:
在这里插入图片描述
DevRTT:SampleRTT与EstimatedRTT的差值
在这里插入图片描述

Karn 算法
在计算平均往返时间RTT时,只要报文段重传了, 就不采用其往返时间样本

TimeoutInterval = TimeoutInterval(last)*y

TCP发送方事件
(1)从应用层收到数据
创建Segment,序列号是Segment第一个字节的编号,开启计时器,设置超时时间:TimeOutInterval

(2)超时
重传引起超时的Segment并重启定时器

(3)收到ACK
如果确认此前未确认的Segment ,更新SendBase,如果窗口中还有未被确认的分组,重新启动定时器

TCP发送端程序

NextSeqNum = InitialSeqNum TCP发送端程序
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 */

重传示例
在这里插入图片描述
丢失ACK:当定时器时间超时,发送方就会重新发送报文
定时器时间设置过短:发送方一下发送两个报文,当第一个报文还没有返回给发送方,时间超时,发送方会再次发送报文,过一会,服务器的报文到达发送方,返回ACK=100,ACK=120,第二次的报文返回ACK=120,因为都收到了两个报文返回

3.快速重传机制

TCP的 实现中,如果发生超时,超时时间间隔将重新设置,即将超时时间间隔加倍,导致其很大

通过重复ACK检测分组丢失,Sender会背靠背地发送多个分组,如果某个分组丢失,可能会引发多个重复的ACK,如果sender收到对同一数据的3个ACK,则假定该数据之后的段已经丢失在定时器超时之前即进行重传(快速重传)

快速重传算法

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
		}
	......

三、TCP流量控制

流量控制 :发送方不会传输的太多、太快以至于淹没接收方(buffer溢出)
TCP利用滑动窗口机制实现流量控制

在通信过程中,接收方根据自己接收缓存的大小,动态地调整发送方的发送窗口大小,这称为接收窗口, 即调整TCP报文段首部中的“窗口”字段值,来限制发送方向网络注入报文的速率

发送方根据其对当前网络拥塞程序的估计而确定的窗口值,这称为拥塞窗口其大小与网络的带宽和时延密切相关

接收方为TCP连接分配buffer
在这里插入图片描述
Buffer中的可用空间 :
spareroom= RcvWindow
= RcvBuffer-[LastByteRcvd -LastByteRead]

Receiver通过在Segment的头部字段将RcvWindow 告诉Sender,Sender限制自己已经发送的但还未收到ACK的数据不超过接收方的空闲RcvWindow尺寸

四、TCP连接管理

TCP连接的建立采用C/S模式,主动发起连接建立的应用进程叫做客户,而被动等待连接建立的应用进程叫做服务器
在这里插入图片描述
TCP sender和receiver在传输数据前需要建立连接
建立连接前的准备:
(1)初始化TCP变量

1.Seq,标明本次报文段数据部分的第一个字节的序号
2.Buffer和流量控制信息

(2)Client:连接发起者

Socket clientSocket = new Socket("hostname","port number");

(3)Server: 等待客户连接请求

Socket connectionSocket = welcomeSocket.accept();

1.连接建立 — 三次握手

TCP建立过程图解
在这里插入图片描述

第一步:客户机的TCP首先向服务器的TCP发送一个连接请求报文段,这个特殊的报文段中不含应用层数据SYN标志位被置为1。客户机会==随机选择一个起始序号 seq=client_isn ==(连接请求报文不携带数据,但要消耗一个序号)

第二步:服务器的TCP收到连接请求报文段后,若同意建立连接,就向客户机发回确认,并为该TCP连接分配TCP缓存和变量,在确认报文段中,SYN和ACK位都被置为1(图中没有ACK), 确认号字段的值为ack=client_isn+ 1, 并且服务器随机产生起始序号seq = server_isn(确认报文不携带数据,但也要消耗-一个序号),确认报文段同样不包含应用层数据

第三步:当客户机收到确认报文段后,还要向服务器给出确认,并且要给该连接分配缓存和变量,报文段的ACK标志位被置1,序号字段为client_isn+ 1,确认号字段ack= server_isn+1, 该报文段可以携带数据,若不携带数据则不消耗序号

成功进行以上三步后,就建立了TCP连接,接下来就可以传送应用层数据

注:
(1)服务器端的资源是在完成第二次握手时分配的

(2)客户端的资源是在完成第三次握手时分配的,这就使得服务器易于受到SYN洪泛攻击

SYN洪泛攻击
攻击者发送TCP SYN,服务器返回ACK后,该攻击者就不对其进行确认,那么这个TCP连接处于挂起状态,所谓的半连接状态服务器收不到再确认的话,还会重复发送ACK给攻击者,这样就更加浪费服务器资源

攻击者如果发送非常大量的这种TCP连接,由于每一个都无法完成三次握手,所以服务器上这些TCP连接会因为挂起状态而消耗CPU和内存,最后服务器可能死机,就无法为正常用户提供服务

解决办法:SYN cookie

2.连接释放 — 四次挥手

连接释放过程图解
在这里插入图片描述
第一步:客户机打算关闭连接时,向服务器发送一个连接释放报文段, 并停止发送数据,主动关闭TCP连接,该报文段的FIN标志位被置1, seq=u(它等于前面已传送过的数据的最后一个字节的序号加1) ,FIN报文段即使不携带数据,也要消耗一个序号

TCP 是全双工的,即可以想象为一条TCP连接上有两条数据通路,但在发送FIN报文时,发送FIN的一端不能再发送数据,即关闭了其中一条数据通路,但对方还可以发送数据

第二步:服务器收到连接释放报文段后即发出确认,确认号是ack=u+ 1,这个报文段自己的序号是v(等于它前面已传送过的数据的最后一个字节的序号加1)

此时,从客户机到服务器这个方向的连接就释放了,TCP连接处于半关闭状态。但服务器若发送数据,客户机仍要接收,即从服务器到客户机这个方向的连接并未关闭

第三步:若服务器已经没有要向客户机发送的数据,就通知TCP释放连接,此时其发出FIN= 1的连接释放报文段

第四步:客户机收到连接释放报文段后,必须发出确认,在确认报文段中,ACK字段被置为1,此时TCP连接还未释放,必须经过时间等待计时器设置的时间2MSL后,客户机才进入连接关闭状态。但是,只要服务器收到客户机发送的确认就关闭。

注:关于连接和释放,ACK、 SYN、 FIN 一定等于1

连接过程中客户机和服务器的状态:
在这里插入图片描述

五、TCP拥塞控制

1.基本原理

拥塞控制指防止过多的数据注入网络,保证网络中的路由器或链路不致过载

出现拥塞时,端点并不了解到拥塞发生的细节,对通信连接的端点来说,拥塞往往表现为通信时延的增加

拥塞控制 VS 流量控制
相同点:它们都通过控制发送方发送数据的速率来达到控制效果

不同点:
拥塞控制是让网络能够承受现有的网络负荷,是一个全局性的过程,涉及所有的主机、所有的路由器,以及与降低网络传输性能有关的所有因素

流量控制往往是指点对点的通信量的控制,即接收端控制发送端,它所要做的是抑制发送端发送数据的速率,以便使接收端来得及接收

控制原理:
(1)Sender限制发送速率
通过设置CongWin(拥塞窗口)的大小,流量控制哪里介绍过

(2)CongWin(拥塞窗口):动态调整以改变发送速率,反映所感知到的网络拥塞

(3)如何感知网络拥塞?
Loss事件=timeout或3个重复ACK,发生loss事件后,发送方降低速率

(4)如何合理地调整发送速率?
1.加性增—乘性减: AIMD
2.慢启动: SS

2.慢启动(SS)

原理: 当连接开始时,指数性增长

在TCP刚刚连接好并开始发送TCP报文段时,先令拥塞窗口CongWin= 1,即一个最大报文段长度MSS

每收到一个对新报文段的确认后,将CongWin加1,即增大一个 MSS,用这样的方法逐步增大发送方的拥塞窗口CongWin,可使分组注入网络的速率更加合理,因为在开始的时候,可用带宽可能远远高于初始传输速率
在这里插入图片描述
指数性增长:每个RTT(也叫做传输轮次)将CongWin翻倍,收到每个ACK进行操作,初始速率很慢,但是快速攀升

3.加性增—乘性减(AIMD)

原理:逐渐增加发送速率,谨慎探测可用带宽,直到发生loss

加性增: 每个RTT将CongWin增大一个MSS——拥塞避免
乘性减: 发生loss后将CongWin减半也称为快恢复

何时应该指数性增长切换为线性增长(拥塞避免)?

设置变量 Threshold,当慢启动将拥塞窗口增大到Threshold慢启动阈值,改用AIMD(拥塞避免)
在这里插入图片描述

Loss事件发生时, Threshold被设为Loss事件前CongWin值的1/2(黑线是正确的)

例题: 一个TCP连接总是以1 KB的最大段长发送TCP段,发送方有足够多的数据要发送。当拥塞窗口为16 KB时发生了超时,如果接下来的4个RTT(往返时间)时间内的TCP段的传输都是成功的,那么当第4个RTT时间内发送的所有TCP段
都得到肯定应答时,拥塞窗口大小是多少?

threshold=16/2=8 KB, CongWin=1 KB, 1个RTT后, CongWin=2 KB ,
2个RTT后, CongWin=4 KB ,3个RTT后, CongWin=8 KB ,Slowstart isover;
4个RTT后, CongWin=9 KB

总结

提示:这里对文章进行总结:

热门文章

暂无图片
编程学习 ·

C语言二分查找详解

二分查找是一种知名度很高的查找算法,在对有序数列进行查找时效率远高于传统的顺序查找。 下面这张动图对比了二者的效率差距。 二分查找的基本思想就是通过把目标数和当前数列的中间数进行比较,从而确定目标数是在中间数的左边还是右边,将查…
暂无图片
编程学习 ·

GMX 命令分类列表

建模和计算操作命令: 1.1 . 创建拓扑与坐标文件 gmx editconf - 编辑模拟盒子以及写入子组(subgroups) gmx protonate - 结构质子化 gmx x2top - 根据坐标生成原始拓扑文件 gmx solvate - 体系溶剂化 gmx insert-molecules - 将分子插入已有空位 gmx genconf - 增加…
暂无图片
编程学习 ·

一文高效回顾研究生课程《数值分析》重点

数值分析这门课的本质就是用离散的已知点去估计整体,就是由黑盒子产生的结果去估计这个黑盒子。在数学里这个黑盒子就是一个函数嘛,这门课会介绍许多方法去利用离散点最大化地逼近这个函数,甚至它的导数、积分,甚至微分方程的解。…
暂无图片
编程学习 ·

在职阿里5年,一个28岁女软测工程师的心声

简单的先说一下,坐标杭州,14届本科毕业,算上年前在阿里巴巴的面试,一共有面试了有6家公司(因为不想请假,因此只是每个晚上去其他公司面试,所以面试的公司比较少) ​ 编辑切换为居中…
暂无图片
编程学习 ·

字符串左旋c语言

目录 题目: 解题思路: 第一步: 第二步: 第三步: 总代码: 题目: 实现一个函数,可以左旋字符串中的k个字符。 例如: ABCD左旋一个字符得到BCDA ABCD左旋两个字符…
暂无图片
编程学习 ·

设计模式--观察者模式笔记

模式的定义与特点 观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式&#xf…
暂无图片
编程学习 ·

睡觉突然身体动不了,什么是睡眠痽痪症

很多朋友可能有这样的体验,睡觉过程中突然意识清醒,身体却动弹不了。这时候感觉非常恐怖,希望旁边有一个人推自己一下。阳光以前也经常会碰到这样的情况,一年有一百多次,那时候很害怕晚上到来,睡觉了就会出…
暂无图片
编程学习 ·

深入理解C++智能指针——浅析MSVC源码

文章目录unique_ptrshared_ptr 与 weak_ptrstd::bad_weak_ptr 异常std::enable_shared_from_thisunique_ptr unique_ptr 是一个只移型别(move-only type,只移型别还有std::mutex等)。 结合一下工厂模式,看看其基本用法&#xff…
暂无图片
编程学习 ·

@TableField(exist = false)

TableField(exist false) //申明此字段不在数据库存在,但代码中需要用到它,通知Mybatis-plus在做写库操作是忽略它。,.
暂无图片
编程学习 ·

Java Web day15

第十二章文件上传和下载 一、如何实现文件上传 要实现Web开发中的文件上传功能,通常需要完成两步操作:一.是在Web页面中添加上传输入项;二是在Servlet中读取上传文件的数据,并保存到本地硬盘中。 需要使用一个Apache组织提供一个…
暂无图片
编程学习 ·

【51nod 2478】【单调栈】【前缀和】小b接水

小b接水题目解题思路Code51nod 2478 小b接水 题目 输入样例 12 0 1 0 2 1 0 1 3 2 1 2 1输出样例 6解题思路 可以发现最后能拦住水的都是向两边递减高度(?) 不管两个高积木之间的的积木是怎样乱七八糟的高度,最后能用来装水的…
暂无图片
编程学习 ·

花了大半天写了一个UVC扩展单元调试工具

基于DIRECTSHOW 实现的,用的是MFC VS2019. 详见:http://www.usbzh.com/article/detail-761.html 获取方法 加QQ群:952873936,然后在群文件\USB调试工具&测试软件\UVCXU-V1.0(UVC扩展单元调试工具-USB中文网官方版).exe USB中文网 USB中文…
暂无图片
编程学习 ·

贪心(一):区间问题、Huffman树

区间问题 例题一:区间选点 给定 N 个闭区间 [ai,bi]请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。 输出选择的点的最小数量。 位于区间端点上的点也算作区间内。 输入格式 第一行包含整数 N,表示区间数。 接下来 …
暂无图片
编程学习 ·

C语言练习实例——费氏数列

目录 题目 解法 输出结果 题目 Fibonacci为1200年代的欧洲数学家,在他的着作中曾经提到:「若有一只免子每个月生一只小免子,一个月后小免子也开始生产。起初只有一只免子,一个月后就有两只免子,二个月后有三只免子…
暂无图片
编程学习 ·

Android开发(2): Android 资源

个人笔记整理 Android 资源 Android中的资源,一般分为两类: 系统内置资源:Android SDK中所提供的已经定义好的资源,用户可以直接拿来使用。 用户自定义资源:用户自己定义或引入的,只适用于当前应用的资源…
暂无图片
编程学习 ·

零基础如何在短时间内拿到算法offer

​算法工程师是利用算法处理事物的职业 算法(Algorithm)是一系列解决问题的清晰指令,也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。 如果一个算法有缺陷,或不适合于某个问题,执…
暂无图片
编程学习 ·

人工智能:知识图谱实战总结

人工智能python,NLP,知识图谱,机器学习,深度学习人工智能:知识图谱实战前言一、实体建模工具Protegepython,NLP,知识图谱,机器学习,深度学习 人工智能:知识图…
暂无图片
编程学习 ·

【无标题】

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…