TCP/IP(五):TCP 协议详解

上一节 中讲过,TCP 协议是面向有连接的协议,它具有丢包重发和流量控制的功能,这是它区别于 UDP 协议最大的特点。本文就主要讨论这两个功能。

数据包重发

数据发送

丢包重发的前提是发送方能够知道接收方是否成功的接收了消息。所以,在 TCP 协议中,接收端会给发送端返回一个通知,也叫作确认应答(ACK),这表示接收方已经收到了数据包。

根据上一节对 TCP 首部的分析得知,ACK 的值和下次发送数据包的序列号相等。因此 ACK 也可以理解为:“发送方,下次你从这个位置开始发送!”。下图表示了数据发送与确认应答的过程:


ACK 确认

数据包和 ACK 应答都有可能丢失,在这种情况下,发送方如果在一段时间内没有收到 ACK,就会重发数据:


未收到 ACK 时重发数据

即使网络连接正常,由于延迟的存在,接收方也有可能收到重复的数据包,因此接收方通过 TCP 首部中的 SYN 判断这个数据包是否曾经接收过。如果已经接收过,就会丢弃这个包。

重传超时时间(RTO)

如果发送方等待一段时间后,还是没有收到 ACK 确认,就会启动超时重传。这个等待的时间被称为重传超时时间(RTO,Retransmission TimeOut)。RTO 的值具体是多久呢?

首先,RTO 的值不是固定的,它是一个动态变化的时间。这个时间总是略大于连接往返时间(RTT,Round Trip Time)。这个设定可以这样理解:“数据发送给对方,再返回到我这里,假设需要 10 秒,那我就等待 12秒,如果超过 12 秒,那估计就是回不来了。”

RTT 是动态变化的,因为谁也不知道网络下一时刻是否拥堵。而当前的 RTO 需要根据未来的 RTT 估算得出。RTO 不能估算太大,否则会多等待太多时间;也不能太小,否则会因为网络突然变慢而将不该重传的数据进行重传。

RTO 有自己的估算公式,可以保证即使 RTT 波动较大,它的变化也不会太剧烈。感兴趣的读者可以自行查阅相关资料。

TCP 窗口

按照之前的理论,在数据包发出后,直至 ACK 确认返回以前,发送端都无法发送数据,而且包的往返时间越长,网络利用效率和通信性能就越低。前两张图片形象的解释了这一点。

为了解决这个问题,TCP 使用了“窗口”这个概念。窗口具有大小,它表示无需等待确认应答就可以继续发送数据包的最大数量。比如窗口大小为 4 时,数据发送的示意图如下:


窗口大小为 4

不等确认就连续发送若干个数据包会不会有问题呢?我们首先来看数据包丢失问题。

我们知道 TCP 首部中的 ACK 字段表示接收方已经收到数据的最后位置。因此,接收方成功接收到了 1-1000 字节的数据后,它会发送一个 ACK = 1001 的确认包。假设 1001-2000 字节的数据包丢失了,由于窗口长度比较大,发送方会继续发送 2001-3000 字节的数据包。接收端并不会返回这个数据包的确认,因为它最后收到的数据还是 1-1000 字节的数据包。

因此,接收端返回的数据包的 ACK 依然是 1001。这表示:“喂,发数据的,别往后发了,你第 1001 字节开始的数据还没来呢”。可以想见,发送端以后每次发送数据包得到的确认中,ACK 的值都是 1001。当连续收到三次确认之后,发送方会意识到:“对方还没有接收到数据,这个包需要重传”。

因此,引入窗口的概念后,被发送的数据不能立刻丢弃,需要缓存起来以备将来需要重发。

利用窗口发送数据的过程可以用下图表示:


快速重传

如果是数据包没有丢失,但是确认包丢失了呢?这就是窗口最擅长处理的问题了。假设发送发收到的确认包中的 ACK 第一次是 1001,第二次是 4001。那么我们完全可以相信中间的两个包是成功被接收的。因为如果有没接收到的包,接收方是不会增加 ACK 的。

在这种情况下,如果不使用窗口,发送方就需要重传第二、三个数据包,但是有了窗口的概念后,发送方就省略了两次重传。因此使用窗口实际上可以理解为“空间换时间”。


某些确认包丢失时不用重发

流量控制

窗口大小

如果窗口过大,会导致接收方的缓存区数据溢出。这时候本该被接收的数据反而丢弃了,就会导致无意义的重传。因此,窗口大小是一个可以改变的值,它由接收端主机控制,附加在 TCP 首部的“窗口大小”字段中。

慢启动

在连接建立的初期,如果窗口比较大,发送方可能会突然发送大量数据,导致网络瘫痪。因此,在通信一开始时,TCP 会通过慢启动算法得出窗口的大小,对发送数据量进行控制。

流量控制是由发送方和接收方共同控制的。刚刚我们介绍了接收方会把自己能够承受的最大窗口长度写在 TCP 首部中,实际上在发送方这里,也存在流量控制,它叫拥塞窗口。TCP 协议中的窗口是指发送方窗口和接收方窗口的较小值。

慢启动过程如下:

  1. 通信开始时,发送方的拥塞窗口大小为 1。每收到一个 ACK 确认后,拥塞窗口翻倍。
  2. 由于指数级增长非常快,很快地,就会出现确认包超时。
  3. 此时设置一个“慢启动阈值”,它的值是当前拥塞窗口大小的一半。
  4. 同时将拥塞窗口大小设置为 1,重新进入慢启动过程。
  5. 由于现在“慢启动阈值”已经存在,当拥塞窗口大小达到阈值时,不再翻倍,而是线性增加。
  6. 随着窗口大小不断增加,可能收到三次重复确认应答,进入“快速重发”阶段。
  7. 这时候,TCP 将“慢启动阈值”设置为当前拥塞窗口大小的一半,再将拥塞窗口大小设置成阈值大小(也有说加 3)。
  8. 拥塞窗口又会线性增加,直至下一次出现三次重复确认应答或超时。

以上过程可以用下图概括:


窗口大小变化示意图

强烈建议读者对照上述八个步骤理解这幅图!



文/bestswifter(简书作者)
原文链接:http://www.jianshu.com/p/d9edbba4035b
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/248005.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TCP/IP(六):HTTP 与 HTTPS 简介

本文是准备面试过程中网络部分总结整理的最后一篇文章,主要介绍以下知识: HTTP 协议概述POST 请求和 GET 请求Cookie 和 Session数据传输时的加密HTTPS 简介 HTTP 协议 在 OSI 七层模型中,HTTP 协议位于最顶层的应用层中。通过浏览器访问网…

Node — 第三天

模块化 什么是模块化 模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。 对于整个系统来说,模块是可组合、分解和更换的单元。 生活中的模块化 编程中的模块化 编程领域中的模块化,就是遵守固定的规则,…

FireDAC 中文字段过滤问题

当使用 FireDAC Filter 过滤数据的时候,通常这样写: FDMemTable.Filtered : False; FDMemTable1.Filter : 姓名 string(edtFilter.Text).QuotedString; FDMemTable.Filtered : True; 将会报错:[FireDAC][Stan][Eval]-107. Invalid characte…

Express — 使用步骤

Express Express 介绍安装搭建服务器的步骤express提供的新方法GET接口 获取GET中的请求参数 POST接口 获取POST请求提交的数据 中间件原理中间件语法中间件初体验(设置响应头)中间件开放静态资源中间件接收POST请求体中间件返回404页面 express 介绍 E…

大模型工具_Langchain-Chatchat

https://github.com/chatchat-space/Langchain-Chatchat 原Langchain-ChatGLM 1 功能 整体功能,想解决什么问题 基于 Langchain 与 ChatGLM 等LLM模型,搭建一套针对中文场景与开源模型,界面友好、可离线运行的知识库问答解决方案。 当前解决…

iOS 键盘风格详解UIKeyboardType

一、键盘风格 UIKit框架支持8种风格键盘。 [java] view plaincopy print?typedef enum { UIKeyboardTypeDefault, // 默认键盘:支持所有字符 UIKeyboardTypeASCIICapable, // 支持ASCII的默认键盘 UIKeyboardTypeNu…

Node — 第四天(Promise与路由)

Promise - ES6新对象 Promise能够处理异步程序。 回调地狱 JS中或node中,都大量的使用了回调函数进行异步操作,而异步操作什么时候返回结果是不可控的,如果我们希望几个异步请求按照顺序来执行,那么就需要将这些异步操作嵌套起来…

winform datagridview控件使用

最近做项目时&#xff0c;显示查询结果总需要绑定到datagridview控件上显示&#xff0c;总结了给datagridview绑定数据的方式&#xff0c;以及导出datagridview数据到excel表格&#xff0c;如有错误请多指教 1.直接绑定数据源&#xff0c;可以绑定的数据格式有List<T>,Da…

Node — 第五天

1. MySQL数据库 phpstudy 数据库服务器及图形化软件 软件链接 链接&#xff1a;https://pan.baidu.com/s/1F8wdoMstHAJkINfDKDejsw 提取码&#xff1a;xl3k 数据库对于我们前端同学来说&#xff0c;就是一个了解。 对于不会变化的数据&#xff08;省、市、县&#xff09;&…

iOS10 权限访问崩溃

手机升级了 iOS10 Beta&#xff0c;然后用正在开发的项目 装了个ipa包&#xff0c;发现点击有关 权限访问 直接Crash了&#xff0c;并在控制台输出了一些信息&#xff1a; This app has crashed because it attempted to access privacy-sensitive data without a usage descr…

Node — 第六天(前后端分离)及(身份验证)

综合应用服务端知识点搭建项目 下载安装所需的第三方模块 npm init -y npm i express cors mysql # express 用于搭建服务器 # cors 用于解决跨域 # mysql 用于操作数据库# 后面用到什么&#xff0c;再下载创建app.js 之前&#xff0c;我们开启一个服务器&#xff0c;js文件…

继承上机作业

1、实现如下类之间的继承关系&#xff0c;并编写Music类来测试这些类 2、编写一个Java应用程序&#xff0c;该程序包括3个类&#xff1a;Monkey类、People类和主类E。要求&#xff1a; (1) Monkey类中有个构造方法&#xff1a;Monkey (String s)&#xff0c;并且有个public voi…

ApplePay集成教程

Apple Pay运行环境&#xff1a;iPhone6以上设备&#xff0c;操作系统最低iOS9.0以上&#xff0c;部分信息设置需要iOS9.2以上。目前还不支持企业证书添加。 环境搭建好后可以在模拟器上面运行&#xff0c;xcode7.2.1iPhone6SP9.2系统下&#xff0c;系统会绑定几种虚拟的银行卡…

Node — 第七天 (大事件项目接口实现一)

关于JS错误处理 node中和mysql中的错误处理 node和MySQL提供的方法&#xff0c;已经对错误信息进行了封装&#xff0c;只需要使用 err.message 即可获取到错误信息。 比如&#xff1a; const fs require(fs); // 读取一个不存在的文件 fs.readFile(abcd.txt, (err, data) …

1.Consul 简介和环境搭建

1.什么是 Consul Consul 是 service mesh(服务网格)的一个解决方案&#xff0c;它提供了诸如服务发现&#xff0c;配置和隔离等功能的一整套控制平面(control plane)。开发人员可以根据需要单独使用这些功能点&#xff0c;也可以将他们整合成为一个完整的service mesh。Consul …

Node — 第八天 (大事件项目接口实现二)

如何处理MySQL的错误 MySQL的错误信息&#xff0c;可以通过err来获取。这是没有问题的。 但是&#xff0c;我们加入了Promise&#xff0c;Promise中的错误&#xff0c;在外部是获取不到的&#xff0c;只能使用Promise相关方法来获取错误信息。 解决方法一 使用 JS原生的 tr…

在local模式下的spark程序打包到集群上运行

一、前期准备 前期的环境准备&#xff0c;在Linux系统下要有Hadoop系统&#xff0c;spark伪分布式或者分布式&#xff0c;具体的教程可以查阅我的这两篇博客&#xff1a; Hadoop2.0伪分布式平台环境搭建 Spark2.4.0伪分布式环境搭建 然后在spark伪分布式的环境下必须出现如下八…

APS系统对制造企业到底有多重要?看完这5点你就明白了

第一个问题&#xff1a;需要APS吗&#xff1f; APS是否重要&#xff0c;不能从其所体现的软件工具或系统角度来说&#xff0c;而应该从业务角度来说。对于制造工厂和车间的运行而言&#xff0c;计划是核心的业务。就如同那句俗话说的&#xff0c;没有规矩不成方圆&#xff0c;领…

Node — 第九天 (大事件项目接口实现三)

文章管理接口 设计数据表 添加文章接口 编写接口&#xff0c;使用postman模拟提交formdata类型的数据 在article.js 中&#xff0c;加入 /add 路由 postman模拟提交formdata类型的数据 multer处理文件上传 下载安装multer 加载模块 const multer require(multer) 配置上…

Node — 第九天 (ES6降级 and 发布属于自己的[第三方模块]包)

ES6降级处理 因为 ES 6 有浏览器兼容性问题&#xff0c;可以使用一些工具进行降级处理&#xff0c;例如&#xff1a;babel 降级处理 babel 的使用步骤 安装 Node.js命令行中安装 babel配置文件 .babelrc运行命令&#xff0c;完成降级 项目初始化 (项目文件夹不能有中文) npm …