网络原理之 TCP 协议

目录

1. TCP 协议格式

2. TCP 原理

(1) 确认应答

(2) 超时重传

(3) 连接管理

a) 三次握手

b) 四次挥手

(4) 滑动窗口

(5) 流量控制

(6) 拥塞控制

(7) 延时应答

(8) 捎带应答

3. TCP 特性

4. 异常情况的处理

1) 进程崩溃

2) 主机关机 (正常流程)

3) 主机掉电 (非正常)

4) 网线断开

5. TCP 和 UDP 之间的对比

6. 基于 TCP 的应用层协议


前文:TCP 的使用

1. TCP 协议格式

想要知道 TCP 的原理,我们首先就得了解 TCP 协议报文的格式。

TCP 数据报分为两部分,报头 + 载荷(应用层数据报),选项(可以有,也可以没有)也是报头中的一部分。

大家都知道,TCP 的特点是:有连接,可靠传输、面向字节流,全双工

其中可靠传输,是 TCP 最最最核心的特性(初心)。

可靠传输,不是说发送方能够 100% 的传输给接收方(再厉害的技术,抵不过挖掘机一铲子)

而是退而求其次:

1) 发送方将数据发出去之后,数据到没到接收端,发送方能心里有数,知道接收方是否收到数据

2) 如果发现接收端没收到数据,能采取一系列的措施进行补救。

那么 TCP 是如何保证可靠传输的呢?这就涉及到一个非常关键的机制,确认应答。

2. TCP 原理

(1) 确认应答

发送方,把数据发给接收端之后,接收端会返回一个应答报文(acknowledge, ack)。

发送方,如果收到这个应答报文了,就说明发送方把数据成功传给对方了。

而在网络传输过程中,因为每个数据包传输是走的路径不同,所以就可能会出现数据包的 "先发后至" 的情况。

举个例子:

为了处理这种情况,TCP 就需要完成两个工作:

1. 确保应答报文和发出去的数据,能够对得上号,不出现歧义。

2. 确保在出现先发后至的现象时,能够让应用程序这边仍然按照正确的顺序来理解数据。

而引入序号和确认序号,给每条数据进行编号,针对性应答,或者按照序号,对数据进行重新排序,就能解决上述问题。

TCP 是按照字节的方式来编序号的,如图:

TCP 的初心就是实现可靠传输,达成可靠传输的核心机制就是确认应答,通过确认应答,发送方就能够知道数据是否到达了接收方。如果数据到达了,那么接收方返回的 ack 里面的确认序号就是下一次发送方发送的数据的第一个字节。如果数据没到达,那么接收方就不会返回 ack。(不考虑滑动窗口的情况下)

那么如何区分一个数据报是普通的数据,还是 ack 应答数据呢?

可以通过 TCP 报文协议中的,六位标志位的 ACK 来确认,数据报是否是应答报文。

如果 ACK = 1,则说明是应答报文,其中的 "确认序号字段" 就能够生效。

如果 ACK = 0,那么数据报中的 "确认序号字段" 不会生效。

确认应答,是 TCP 最核心的机制,支持了 TCP 的可靠传输。

但是仅仅只有确认应答还不够,还需要其他的机制来辅助,超时重传就是这样的一个辅助机制。

(2) 超时重传

确认应答,描述的是一个比较理想的情况,

如果网络传输中,出现丢包了,那么发送方就没有办法收到 ack 了,那该怎么办呢?

通过超时重传,就可以解决上述问题。超时重传,是针对确认应答机制的补充。

超时重传,就是等待一定的超时时间,发送方还没有收到 ACK,发送方会主动把刚刚的数据重新传输一遍给接收端。

可以先来思考一下,为什么会出现丢包。

因为丢包是一个随机的事件,所以在 TCP 传输过程中,丢包就存在两种情况:

第一种是发送方发的数据报丢了,第二种是接收方发送的应答报文丢了。

如图:

所以当引入可靠性的时候,是会付出代价的,最明显的两方面:

1. 传输效率    因为有超时重传,所以传输数据效率不高。(这也是 UDP 不会被 TCP 完全取代的意义)

2. 复杂程度

这里其实还有一个问题:

(3) 连接管理

连接管理就是建立连接和断开连接。

其实 TCP 建立连接的过程也叫做三次握手,断开连接的过程叫做四次挥手。

那这个握手到底是什么意思呢?

其实握手就是打个招呼,就是给对方传输一个简短的,没有业务数据的数据报,通过这个数据报来唤起对方的注意,从而触发后续的操作。四次挥手的 "挥手" 和三次握手的 "握手" 是同一个意思。

举个例子:比如说你走路遇到熟人的时候,对方主动跟你说 "你好" "hello" 之类的,打招呼的内容通常没有什么实际的意义,就只是起到唤起对方的注意力的效果。

前面也提到过,TCP 是有连接的,需要主机双方各自保存对端的信息

a) 三次握手

那 TCP 的三次握手具体流程是怎样的呢?

TCP 的三次握手,TCP 在建立连接的时候,需要通信双方一共打三次招呼,才能完成建立连接。

TCP 的初心,是为了实现可靠传输,确认应答是核心,超时重传等机制是辅助。

但进行确认应答和超时重传有个大前提,那就是当前的网络环境是基本可用的,通畅的,

如果当前网络已经存在重大故障了,那么可靠传输是无从谈起的。

三次握手的核心作用一:

投石问路,确认当前网络是否是畅通的。

如果连 syn 和 ack 这样没携带业务数据的数据报都不能够正常传输的话,那么之后要传输的携带了业务的数据报也不可能正常传输。

三次握手的核心作用二:

让发送方和接收方都能确定自己的发送能力和接收能力均正常。

三次握手的核心作用三:

让通信双方,在握手过程中,针对一些重要的参数,进行协商。

TCP 通信过程中,序号是从几开始,就是双方协商出来的(一般不是从 1 开始),

每次连接建立的时候,都会协商出一个比较大的,和上次不太一样的值。

这样做是放了防止上一次遗留的数据,影响到本次数据的传输。

有的时候,网络如果不太好,那么客户端和服务器就会断开,再重新建立连接,重连的时候,就有可能在新的连接建立好的时候,旧的数据姗姗来迟,这种迟到的数据报,是应该被丢弃的,而根据本次连接的正常数据报的序号,对比收到的数据报的序号,如果发现差别非常大的话,就说明收到的数据报是旧连接迟到的数据报,那就可以直接丢弃掉。

三次握手可以的话,那四次握手行不行?两次握手行不行?

四次握手是可以的,但是没必要,将中间的两次合并成一次能够提升效率。

两次握手是不可以的,因为少了最后一次的握手,服务器就无法确定自己的发送能力是否正常和客户端的接收能力是否正常。

b) 四次挥手

断开连接的过程就是四次挥手,和三次握手类似。

TIME_WAIT 的意义就是当主动连接断开方发送完最后一次 ACK 时,先进入 TIME_WAIT 状态,等待 2MSL 的时间,如果在这个时间内,ACK 丢包了,对端重传了 FIN,那么 主动断开连接方就能马上返回 ACK,这样对端重传的 FIN 才有意义。

MSL:是一个可配置的参数,这个参数数值是拍脑门拍出来的。

(4) 滑动窗口

前面的确认应答 ,超时重传,连接管理都是用来保证 TCP 的可靠性的。

滑动窗口是用来提高效率的,其实是一种亡羊补牢。

TCP 因为引入了可靠传输,所以传输的效率不太高(多出了一些等待 ACK 的时间,单位时间内能传输的数据就减少了)

而滑动窗口,就是用来减小可靠传输对性能的影响的。

但是再怎么提高 TCP 的效率,也是不可能超过没有引入可靠传输的 UDP 的效率的。

那么具体滑动窗口是怎么做的才能提高效率呢?

其实 TCP 慢就慢在要等对端的 ACK,那就可以在保证可靠传输的前提下,将等待时间缩小就好了。

那就可以进行批量传输数据,这样做效率就上来了。

效率是提高了,但是 TCP 的核心是可靠传输,在提高效率的前提是数据能可靠传输。

上述滑动窗口中,确认应答是可以正常工作的。

但如果在滑动窗口的过程中,出现丢包了,那该怎么办呢?

这里的重传,相比于前面的超时重传,有些不同。

还是得分两种情况讨论:

如果 ACK 全丢了呢?那此时的网络肯定出现严重故障了,平时丢包率达到 10% 都算是比较严重的了,现在直接丢包率 100% ,就别想着 "可靠传输" 了。

如果通信双方,传输数据的量比较小,也不频繁,就仍然是普通的确认应答和超时重传。

如果通信双方,传输数据的量比较大,也更频繁,就会进入到滑动窗口的模式,按照快速重传的方式处理。

(5) 流量控制

通过滑动窗口的方式传输数据,效率是会提升的。

窗口越大,传输效率就会越大。(一份等待时间,等待的 ack 更多了,总的等待时间就更少了)

那么滑动窗口的窗口大小是设置的越大就越好吗?

显然不是的,提高效率的前提是保证可靠传输,如果因为传输的速度太快,接收方处理不过来,就会导致接收方出现丢包的情况,发送方还得重传。

而流量控制,就是站在接收方的角度,反向制约发送方的传输速度。

发送方发送的速率,不应该超过接收方的处理能力。

那么如何知道接收方的处理能力是多少呢?

如图,可以通过 接收方的接收缓冲区的剩余空间大小,来衡量处理能力的大小。

接收方每次收到数据之后,都会把接收缓冲区剩余空间大小通过 ack 返回给发送方,

发送方就会按照这个数值来调整下一轮的发送速度。

如图:

(6) 拥塞控制

流量控制,考虑的是接收方的处理能力,

但是不仅仅要考虑到接收方的处理能力,还要考虑网络通信过程中经过的节点(路由器/交换机)的处理能力,也就是说,还需要考虑整个通信的路径,如果中间某个节点的传输速度达到了瓶颈,那么此时,也会对整体的传输产生影响。

拥塞控制,就是 考虑/衡量 通信过程中,中间节点的情况。

如图:

但是关键的问题,在于怎么衡量中间节点。

之前接收方的处理能力,是很好衡量的。

由于中间节点,结构更复杂,更难以直接的进行量化。

因此可以使用 "实验" 的方式,来找到合适的值。

可以让发送方先按照比较低的速度开始发送数据(小窗口),如果数据传输过程非常顺利,也没有丢包,那就再尝试使用更大的窗口,更高的速度进行发送(一点一点变化),随着窗口不断增大,达到一定程度,可能中间节点就会出现问题了,此时这个节点就可能会出现丢包。发送方发现丢包了,就把窗口大小再调整小,此时如果发现还是继续丢包,那就继续缩小。如果不丢包了,就继续尝试变大。

在这个过程中,发送方不停的调整自己的窗口大小,逐渐达成一个 "动态平衡".

这种做法,就相当于把 "中间节点" 视为一个整体,通过 "实验" 的方式,来找到中间节点的瓶颈在哪里。

上述过程如图:

流量控制和拥塞控制都是在限制发送方的发送窗口大小,

最终实际发送的窗口大小,是取 流量控制 和 拥塞控制 中的较小值。

(7) 延时应答

A 把数据传给 B,B 就会马上返回 ack 给 A (正常)。

也有的时候,A 传输给 B,此时 B 等一会再返回 ack 给 A (延时应答)。

本质上也是为了提升传输效率。

发送方的窗口大小,就是传输效率的关键。

流量控制这里,就是根据接收方的接收缓冲区的剩余空间,来控制发送方的发送速率的,

如果有办法,能让流量控制得到的窗口更大点,发送速率就更快点(大点的前提是,能让接收方处理的过来)

通过延时返回 ack,给接收方更多的时间读取接收缓冲区的数据,此时接收方读了这个数据之后,缓冲区的剩余空间,就变大了,返回的窗口大小,也就更大了。

比如,初始情况下,缓冲区的剩余空间是 10kb,如果立即返回 ack,就返回了 10kb 这么大的大小窗口。如果延时个 200ms 再返回,那么在这 200ms 的过程中,接收方的应用程序,又读了 2kb,此时,返回的 ack 就是返回 12kb 的窗口了。

延时应答,才促成了前面的四次挥手,能够三次挥完。

(8) 捎带应答

在延时应答的基础上,进一步提高效率。

3. TCP 特性

TCP 的特性是:有连接,可靠传输,面向字节流,全双工

面向字节流的特性是:

传输数据的时候可以非常灵活,可以一次传输一个字节,也可以一次传输多个字节。

但是这里存在一个问题:粘包问题(不是 tcp 独有的,而是面向字节流的机制都有类似的情况)

这里的包指的是应用层数据包,如果同时有多个应用层数据包被传输过去,此时就容易出现粘包问题。

如图:

那么该如何解决粘包问题呢?

核心思路:通过定义好应用层协议,明确应用层数据报之间的边界。

1. 引入分隔符

2. 引入长度

比如使用 \n 作为分隔符:

引入长度:

4. 异常情况的处理

如果在使用 tcp 的过程中,出现意外,会如何处理?

1) 进程崩溃

进程崩溃,本质上就是进程没了,进程终止了,那么文件描述符表就释放了,也就相当于调用 socket.close() ,此时就会触发 FIN,对方收到之后,自然也就会返回 ACK 和 FIN,这边再进行 ACK,这里就是一个正常的四次挥手断开连接的流程。

TCP 的连接,可以独立于进程存在。(进程没了,TCP 连接不一定没)

2) 主机关机 (正常流程)

在进行关机的时候,就是会先触发强制终止进程的操作(相当于 1)

此时就会触发 FIN,对方收到之后,自然会返回 ACK 和 FIN。

此时,不仅仅是进程没了,整个系统也关闭了。如果在系统关闭之前,对端返回的 ACK 和 FIN 到了,此时系统还是可以返回 ACK,进行正常的四次挥手的。如果系统已经关闭了,ACK 和 FIN 迟到了,就无法进行后续 ACK 的响应。站在对端的角度,以为是自己的 FIN 丢包了,就会重传 FIN,连续重传好几次都没有响应,最后对端就会放弃连接(把持有的对端信息删除)。

3) 主机掉电 (非正常)

主机掉电,是一瞬间的事情,还来不及杀进程,也来不及发送 FIN,主机直接就停机了。

1. 如果对端是在发送数据(接收方掉电),发送的数据就会一直等待 ack,触发超时重传,重传好几次还是没有响应,就会触发 TCP 的连接重置功能,发起复位报文段(RST = 1),如果复位报文段发过去之后也没有效果,此时就会释放连接了。

2. 如果对端是在接收数据(发送方掉电),对端还在等待数据到达,等了半天没消息,此时其实也无法区分,是发送方没发消息,还是发送方挂了。

针对这种情况,TCP 提供了心跳包的机制,接收方也会周期性的给发送方发送一个特殊的,不携带业务数据的数据包,并且期望对方返回一个应答,如果对方没有应答,并且重复了多次之后,仍然没有,就视为对方挂了,此时就可以单方面释放连接了。

4) 网线断开

网线断开和刚刚的主机掉电非常类似。

如何识别某个机器是否挂了,一般都是通过心跳来检测的。

5. TCP 和 UDP 之间的对比

TCP 有连接,可靠传输,面向字节流,全双工。

UDP 无连接,不可靠,面向数据报,全双工。

TCP 的优势是可靠传输,TCP 适用于绝大部分场景。

UDP 的优势是更高效率,UDP 适合于对 "可靠性不敏感","性能敏感" 的场景,比如局域网内部(同一个机房)的主机之间的通信。

如果要传输比较大的数据包,TCP 优先。(UDP 有 64kb 的限制)

如果要进行 "广播传输" ,优先考虑 UDP。UDP 天然支持广播,TCP 不支持(得自己写代码实现)

6. 基于 TCP 的应用层协议

  • HTTP
  • HTTPS
  • SSH
  • Telnet
  • FTP
  • SMTP
  • 还包括程序员自身写 TCP 程序时定义的应用层协议

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Python爬虫之selenium库驱动浏览器

目录 一、简介 二、使用selenium库前的准备 1、了解selenium库驱动浏览器的原理 (1)、WebDriver 协议 (2)、 浏览器驱动(Browser Driver) (3)、 Selenium 客户端库 &#xff0…

Vite+Vue3项目实战:组件化开发与通信指南

一、典型的ViteVue3项目结构 续上文成功创建Vue3项目的脚手架,通过visual Studio Code软件打开刚刚创建的文件夹,将会看到这样一个项目结构。 使用Vite构建Vue3项目时,项目结构通常遵循一定的组织规则,以保持代码的清晰和可维护性…

汽车免拆案例 | 2007款宝马650i车发动机偶尔无法起动

故障现象 一辆2007款宝马650i车,搭载N62B48B发动机,累计行驶里程约为26万km。车主反映,发动机偶尔无法起动,故障频率较低,十几天出现1 次,且故障出现时起动机不工作。 故障诊断  接车后试车,…

团队管理中如何做好目标管理

团队管理中的目标管理是确保团队高效运行的核心要素之一。 在目标管理中,清晰的目标设定、合理的资源分配、实时的跟踪与反馈机制是成功的关键。首先,设定SMART目标(具体、可衡量、可达成、相关性强、时间限定)能够有效聚焦团队的…

【力扣热题100】—— Day4.反转链表

你不会永远顺遂,更不会一直年轻,你太安静了,是时候出发了 —— 24.12.2 206. 反转链表 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 示例 1: 输入:head [1,2,3,4,5] 输出&…

【AWS re:Invent 2024】一文了解EKS新功能:Amazon EKS Auto Mode

文章目录 一、为什么要使用 Amazon EKS Auto Mode?二、Amazon EKS自动模式特性2.1 持续优化计算成本2.2 迁移集群操作2.3 EKS 自动模式的高级功能 三、EKS Auto 集群快速创建集群配置四、查看来自 API 服务器的指标五、EKS 相关角色权限设置六、参考链接 一、为什么…

记事本建java及java命名规范

1.桌面开发:c# 2. 记事本建java: 以class的名称(类名)为名,名称.java 编译jdk:javac 名称.java 调动运行jre : java 名称 查看名称.java里面的内容:cat 名称.java java 的命名规范 大驼峰(每个单词首…

过程管理系统(源码+文档+部署+讲解)

本文将深入解析“过程管理系统”的项目,探究其架构、功能以及技术栈,并分享获取完整源码的途径。 系统概述 过程管理系统是一款专为工业设计的综合管理平台,旨在通过集成各种管理流程和功能模块来提高管理效率和安全性。系统提供了从登录系…

期权懂|个股期权交割操作流程是什么样的?

期权小懂每日分享期权知识,帮助期权新手及时有效地掌握即市趋势与新资讯! 个股期权交割操作流程是什么样的? 一、行权申报: 期权买方在行权日通过其经纪商提交行权指令,表明其决定行使期权权利。 二、行权匹配&#xf…

智能仓储:入库业务流程介绍

01 入库流程 入库业务流程,常见过程是这样的: 创建PO单 > 创建到货清单 > 核对货物 > 入库质检 > 货物贴标签 > 上架 > 库存同步 1、创建PO单 po单指的是的采购订单,比如采购了一车货品,这车的货品可以理解…

MySQL并发控制(一):幻读

假设有如下表结构: CREATE TABLE t(id int(11) NOT NULL,c int(11) DEFAULT NULL,d int(11) DEFAULT NULL,PRIMARY KEY (id),KEY c (c) ) ENGINEInnoDB;insert into t values(0,0,0),(5,5,5),(10,10,10),(15,15,15),(20,20,20),(25,25,25); 问:如果执行…

Ubuntu22.04中mysql8 rpm安装

1、安装依赖 sudo apt update sudo apt -y dist-upgrade sudo apt -y install vim net-tools wget gcc make cmake lrzsz sudo apt -y install libmecab2 libjson-perl 2、下载rpm文件 https://dev.mysql.com/downloads/mysql/ https://cdn.mysql.com//Downloads/MySQL-8.0/m…

Intel 性能分析“全家桶” For HPC(一)

本系列是对于HPC应用性能分析涉及的主要方法论及Intel主流工具分享。理解这些方法论将有助于对性能分析结果的理解。同时方法论也可以推广到其他的硬件平台的分析上。除此之外后面也将介绍如何用Vtune, Advisor以及ITAC进行性能分析,以及在性能分析过程中这三种性能…

Qwen1.8B大模型微调流程

提示:本篇笔记是在微调大模型为法律相关模型的教程下记录的,参考的讲解视频在B站上,一搜微调大模型为法律大模型就有很多视频。 文章目录 1. 数据集1.1 数据下载1.2 数据格式转换 2. 模型训练2.1 安装依赖2.2 模型训练 3. 模型推理3.1 LoRA模…

第十六章 使用 iSCSI 服务部署网络存储

1. iSCSI 技术介绍 硬盘是计算机硬件设备中重要的组成部分之一,硬盘存储设备读写速度的快慢也会对服务器的整体性能造成影响。硬盘存储结构、RAID 磁盘阵列技术以及LVM 技术等都是用于存储设备的技术,尽管这些技术有软件层面和硬件层面之分&#xff0c…

【js面试题】JavaScript 中箭头函数与普通函数的深度剖析

在 JavaScript 编程的世界里,函数是极为重要的组成部分。而随着 ES6 的出现,箭头函数成为了 JavaScript 函数家族中的新成员。它与传统的普通函数有着诸多的不同之处,这些差异深刻地影响着我们编写代码的方式以及代码的执行逻辑。本文将对 Ja…

【漫话机器学习系列】Adaboost算法

Adaboost(Adaptive Boosting)是一种经典的集成学习方法,主要思想是通过将多个弱学习器(通常是简单模型,如决策树桩)加权组合,来提升整体模型的预测能力。Adaboost 是一种自适应的学习方法&#…

SQL靶场第四关

sql靶场第四关攻略 输入?id1页面正常 输入?id1发现页面也正常 输入?id1",页面异常,说明存在sql报错注入 在输入?id1" --页面还是报错 1.判断闭合点 我们需要找到闭合点,尝试在双引号后面加个) 输入?id1") --我们发现…

Trunk链路操作题

Trunk链路操作题 论证:

Alogrithm:三色棋

1. 说明 三色旗的问题最早由 E.W.Diikstra 所提出,他所使用的用语为 Dutch Nation Flag(Dijkstra 为荷兰人),而多数的作者则使用 Three-Color Flag 来称之。 假设有一条绳子,上面有红、白、蓝三种颜色的旗子&#xff0…