计算机网络——TCP 协议的三次握手 / 四次挥手

简述

TCP / UDP 协议都是传输层的协议。

UDP 是面向无连接的协议,就是说发送端不在乎消息数据是否传输到接收端了,所以会出现数据丢失的情况,所以可靠性也不高。

TCP 是面向连接的、可靠的、基于字节流的传输层协议。所谓面向连接的,就是必须发送端和接收端必须处于连接状态才能发送数据。可靠的就是无论网路链路出现的什么变化,都可以保证一个报文能够到达接收端。

字节流:用户消息通过 TCP 协议传输时,消息可能会被操作系统分组成多个 TCP 报文,如果接收方的程序如果不知道消息的边界,是无法读出一个有效的用户消息的。

TCP 建立连接

TCP 是面向连接的,所以传输数据前需要和接收端建立连接,通过三次握手来进行。过程如下图:

图片来源: 小林coding

简单描述一下三次握手:

1. 客户端首先初始化自己的序列号,发送带有 SYN 标识的报文给服务端,表示向服务端发起连接。客户端进入 SYN-SEND 状态。

2. 服务端接收到报文之后,同样初始化自己的序列号,同时将确认应答的序列号,也就是收到的客户端的序列号 + 1,返回给客户端发送带有 SYN + ACK 标识的报文,表示我接收到了你的连接请求,并同意连接。服务端进入 SYN-RCVD 状态。

3. 客户端接收到了服务端发来的应答,将收到的客户端的序列号 + 1,再次向服务端发送带有 ACK 表示的报文,表示我接收到你发的应答了,确认进入连接状态。这次握手是可以携带客户端到服务端的数据。客户端进入 ESTABLISHED 状态,在服务端收到客户端的应答之后也进入 ESTABLISHED 状态。

用一个例子来描述三次握手的情况。

为什么是三次握手

主要原因:三次握手是为了阻止重复历史连接的初始化。

设想一个场景,当客户端向服务端发送一个请求连接的报文之后宕机了,报文在到达服务器前被网络阻塞了,此时服务器并没有收到连接请求,状态没有变化。然后客户端重启之后,再次向服务端发送连接的报文。会出现下面的情况。

假设此时旧的请求报文比新的先到达服务端,然后向客户端发送应答报文,都知道,报文里是包含了客户端的序列号的,假设初始序列号是10,而服务端返回的是11(10+1),而客户端在重启之后发送的序列号是20,所以客户端现在期望收到的报文序列号应该是21(20+1),但是此时收到的是11,那么就会向服务端发送 RST 请求报文, 表示出现了历史连接,此次连接中止。(有内鬼,中止交易)。

而后一段时间之后,新发送的连接请求报文到达服务端,之后就会进行正常的 TCP 连接。用一个图来简单描述一下。

那么两次握手能不能解决历史连接的问题呢。

假设两次握手,那么第一次握手服务端收到客户端的SYN 之后,就进入到了 ESTABLISHED 状态,此时服务端是可以向客户端发送数据了,但是这个时候客户端还没有进入到 ESTABLISHED 状态。服务端向客户端发送 SYN+ACK 的报文之后,客户端如果判断此次是历史连接,那么会回复 RST 中断连接。但在这个期间,如果服务端发送了数据,那么发送的数据可能就丢失了,还浪费了资源。

三次握手之所以能解决历史连接的问题,就是因为如果这是历史连接,在第二次握手时服务端并不会进入到 ESTABLISHED 状态,也就不能发送数据给客户端,不会白白浪费资源。而是在客户端确认了不是历史连接的之后转变状态。

其他原因:同步初始序列号,避免浪费资源

1. 第一次握手,客户端向服务端发送报文。

2. 第二次握手,服务端向客户端发送报文,确认了客户端发送正常,服务端接收正常。

3. 第三次握手,客户端最后向服务端应答报文,确认了服务端发送正常,客户端接收正常。

由此确认了客户端和接收端连接正常。因为握手是会交换序列号的,也就是同步序列号,序列号在传输数据时去除重复的数据,可以根据序列号按序接收。

而两次握手不能确保序列号同步,同时不能确认是否连接正常,假如只有两次握手,少了第三次握手,那么服务端不知道客户端的接收是否正常,如果不正常,那么服务端发送的数据就会丢失,浪费了资源。

握手过程中出现了报文丢失怎么办

当第一次握手丢失了,当客户端向服务端第一次握手,然后客户端迟迟收不到服务端的 SYN+ACK 的报文,就会触发超时重传,重传的报文序列号是一样的。

而超时时间和重传次数也有限制,不可能一直让客户端发送连接请求,浪费资源,在Linux 里,重传次数是 5 ,而每次超时时间是上一次的两倍,一般第一次是 1秒,第二次就是2秒,以此类推,5次重传总耗时就是 1+2+4+8+16+31 = 63秒,大约一分钟,如果5次都丢失,那么就不会再进行连接了。

第二次握手丢失。第二次握手包含了给客户端的回应报文 ACK,和服务端发起建立连接的请求报文 SYN ,如果丢失了,客户端会以为第一次握手丢失了,那么会触发超时重传。正常情况下,客户端接收到第二次握手之后会发送 ACK 响应报文给服务端,但是服务端迟迟都收不到,那么服务端也会触发超时重传机制。

第三次握手丢失。第三次握手是客户端发送给服务端的响应报文,如果丢失了,服务端会认为第二次握手丢失了,所以服务端会触发超时重传机制。

TCP 断开连接的四次挥手

TCP 建立连接时需要发送报文,断开连接时同样需要发送报文。

1. 首先客户端想要断开连接,会发送一个带有 FIN 标识的请求报文给服务端。客户端进入 FIN_WAIT_1 状态。

2. 服务端接收到报文之后会回复给客户端一个带有 ACK 标识的应答报文。服务端进入 CLOSE_WAIT 状态。客户端接收到 ACK 报文之后进入 FIN_WAIT_2 状态。

3. 因为想要断开连接时服务端可能还有数据没有处理完,所以需要等待处理完成,处理完成之后会发送带有 FIN 标识的请求报文给客户端。服务端进入 LAST_ACK 状态。

4. 客户端接收到报文之后最后返回带有 ACK 标识的应答报文给服务端,客户端进入 TIME_WAIT  状态。服务端接收到ACK 报文之后进入到 CLOSE 状态。一段时间之后,客户端会进入 CLOSE 状态,双方都关闭连接。

图片来源 小林coding

可以用打电话的方式来打个比方。

为什么要挥手四次

从每次挥手发送带有标识的报文可以看出来,关闭连接时,客户端向服务端发送 FIN 报文,只是代表客户端已经发送数据完毕了,但是还能接收数据,同样的服务端也是这样。

服务端收到 FIN 报文时,回复一个 ACK 应答报文,表示我收到了你的请求,但是你先等等,我还有数据没处理完,等到我数据处理完了,我再发送客户端一个 FIN 报文表示我也没数据需要处理和发送了。

假设少了一次挥手,比如说服务端只发送了 ACK 报文,客户端就关闭连接的话,会导致还未处理和发送的数据出现错误或者丢失。

不过,在特定情况下,可以将四次挥手合并成三次挥手。比如服务端也没有数据处理和发送时,TCP 存在延迟确认机制且是默认开启的,那么第二次和第三次就会合并,变成三次挥手。

挥手丢失的话会发生什么

和握手相同,如果握手丢失了,发送方迟迟收不到回应,就会认为刚刚的报丢失了,就会触发超时重传机制。同样的是 ACK 报文是不会重传的,假如第二次挥手丢失了,那么客户端收不到 ACK 应答报文,那么就会认为FIN 报文丢失了,那么就会重传 FIN 报文。

简单来说,当前最近的 FIN 报文发送方会经常重传 FIN 报文。

为什么第四次挥手客户端需要等待 2*MSL(报文最长寿命)时间后才进入 CLOSE 状态

在第三次挥手时,服务端会发送 FIN 报文给客户端,关闭连接,但是如果出现了第三次或者第四次挥手丢失的情况,服务端都会触发超时重传机制来重新发送 FIN 报文。

MSL 一个片段在网络中最大的存活时间,2MSL 就是一个发送和一个回复所需的最大时间,如果这个大于这个时间客户端还没有收到服务端重新发送的 FIN 报文,那么客户端就认为服务端已经接收到了自己发送的 ACK 应答报文,然后进行 CLOSE 状态,代表 TCP 连接完成中断。

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

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

相关文章

机器学习算法手撕(一):KD树

import math import matplotlib.pyplot as pltclass Node:def __init__(self, data, leftNone, rightNone):self.data dataself.left leftself.right right# 创建KDTree类 class KDTree:def __init__(self, k):self.k kdef create_tree(self,dataset,depth):if not dataset…

SpringBoot使用rsa-encrypt-body-spring-boot实现接口加解密

废话不多说&#xff0c;直接上代码 引入依赖 <dependency><groupId>cn.shuibo</groupId><artifactId>rsa-encrypt-body-spring-boot</artifactId><version>1.0.1.RELEASE</version> </dependency>配置文件 rsa:encrypt:# 是…

电表远传抄表是什么?

1.电表远传抄表&#xff1a;简述 电表远传抄表&#xff0c;又称为远程控制自动抄表系统&#xff0c;是电力行业的智能化技术运用&#xff0c;它通过无线或通信网络技术&#xff0c;完成对电表数据信息的远程收集解决。此项技术不仅提升了抄水表高效率&#xff0c;降低了人工偏…

Java订餐系统源码 springboot点菜系统源码

Java订餐系统源码 springboot点菜系统源码 源码下载地址&#xff1a;https://download.csdn.net/download/xiaohua1992/89341358 功能介绍&#xff1a; 前台登录&#xff1a;前台登录&#xff1a; ①首页&#xff1a;菜品信息推荐、菜品信息展示、查看更多 ②菜品信息&…

【剑指offer】2.2编程语言(p22-p25)——面试题1:string赋值运算函数

本节博客是对阅读剑指offer后的笔记归纳总结&#xff0c;有需要借鉴即可。 目录 1.p21-p25内容概要2.询问语法概念常考&#xff1a;CPP关键字理解举例&#xff1a;sizeof空类 3.分析代码举例&#xff1a;类中拷贝构造的无限递归问题 4.写代码常考点&#xff1a;类内成员函数、迭…

keycloakAsana SSO对接配置

说明&#xff1a;Keycloak与Asana单点登录对接&#xff0c;Keycloak做IDP&#xff0c;Asana做SP&#xff1b; 一、环境信息 操作系统&#xff1a;ubuntu keycloak&#xff1a;21.1.2 Asana enterprise&#xff1b;更新apt软件包索引&#xff1a; sudo apt update检查是否已安…

数组-最接近给出数字的三数之和

题目描述 解题思路 这里使用三层for循环&#xff0c;暴力解法穷举所有三个数和的可能性&#xff0c;注意三层循环里的索引不要重复。 代码实现 import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返…

Introduction of Internet 计算机网络概述

计算机网络的概念 计算机网络的定义&#xff1a; 多台独立的计算机通过通信线路实现资源共享的计算机系统 计算机网络的组成 资源子网&#xff1a;提供共享的软件资源和硬件资源 通信子网&#xff1a;提供信息交换的网络结点和通信线路 计算机网络类型 按照拓扑排序 星型…

Transformer详解(1)-结构解读

Transormer块主要由四个部分组成&#xff0c;注意力层、位置感知前馈神经网络、残差连接和层归一化。 1、注意力层(Multi-Head Attention) 使用多头注意力机制整合上下文语义&#xff0c;它使得序列中任意两个单词之间的依赖关系可以直接被建模而不基于传统的循环结构&#…

【C语言】八进制、十六进制

前言 在我们日常生活中使用的数往往是十进制的&#xff0c;而当我们学习C语言后我们会接触到许多不同的进制并且时常需要去思考与使用这些不同的进制&#xff08;尤其是2的幂相关的进制&#xff0c;因为这种计数系统比十进制更接近于计算机的二进制系统&#xff09;&#xff0…

【Linux初探】:解锁开源世界的神秘钥匙

文章目录 &#x1f680;一、了解Linux&#x1f525;二、Linux 的发行版❤️三、Linux应用领域&#x1f4a5;四、Linux vs Windows & mac &#x1f680;一、了解Linux Linux是一种自由、开放源代码的操作系统&#xff0c;它的内核由芬兰计算机科学家Linus Torvalds在1991年创…

手把手从0到1教你做STM32+FreeRTOS智能家居--第10篇之ASR-PRO语音识别模块

前言 先看实验效果&#xff0c;通过ASR-PRO语音智能识别控制模块&#xff0c;来控制STM32单片机实现对应的控制功能。因为后台好多小伙伴私信问用的是什么语音模块&#xff0c;并且很少在网上看到如何使用此模块相关的文章&#xff0c;所以我将会在本篇文章详细介绍一下此模块…

HTML蓝色爱心

目录 写在前面 HTML入门 完整代码 代码分析 运行结果 系列推荐 写在后面 写在前面 最近好冷吖&#xff0c;小编给大家准备了一个超级炫酷的爱心&#xff0c;一起来看看吧&#xff01; HTML入门 HTML全称为HyperText Markup Language&#xff0c;是一种标记语言&#…

【wiki知识库】01.wiki知识库前后端项目搭建(SpringBoot+Vue3)

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 &#x1f33c;环境准备 想要搭建自己的wiki知识库&#xff0c;要提前搭建好自己的开发环境&#xff0c;后端我使用的是SpringBoot&#xff0c;前端使用的是Vue3&#xff0c;采用前后端分离的技术实现。同时使用了Mysql数…

浪潮信息IPF24:AI+时代,创新驱动未来,携手共创智慧新纪元

如今&#xff0c;数字化时代的浪潮席卷全球&#xff0c;人工智能已经成为推动社会进步的重要引擎。浪潮信息IPF24作为行业领先的AI技术盛会&#xff0c;不仅为业界提供了交流合作的平台&#xff0c;更在激发创新活力、拓展发展路径、加速AI技术落地等方面发挥了重要作用。 升级…

【调和级数】100321. 优质数对的总数 II

本文涉及知识点 调和级数 质数、最大公约数、菲蜀定理 LeetCode100321. 优质数对的总数 II 给你两个整数数组 nums1 和 nums2&#xff0c;长度分别为 n 和 m。同时给你一个正整数 k。 如果 nums1[i] 可以被 nums2[j] * k 整除&#xff0c;则称数对 (i, j) 为 优质数对&#…

手机版AI写作软件哪个好用?5款AI写作软件分享

在这个快节凑的时代&#xff0c;人们对于高效、便捷的创作方式很是追求。尤其是在人工智能技术发展迅速的今天&#xff0c;AI写作软件的出现&#xff0c;让很多自媒体创作者都会想到在手机上面进内容创作&#xff0c;这样不仅能提高工作效率&#xff0c;而且工作的自由度会更高…

ciscn2024(上传一下,有侵权什么的问题的话联系删除)

Web Simple_php 这个Simple_php一点儿也不Simple (⋟﹏⋞) 源码放这儿了&#xff1a; <?phpini_set(open_basedir, /var/www/html/); error_reporting(0);if(isset($_POST[cmd])){$cmd escapeshellcmd($_POST[cmd]); if (!preg_match(/ls|dir|nl|nc|cat|tail|more|flag…

Java中IO流类的体系

Java为我们提供了多种多样的IO流&#xff0c;我们可以根据不同的功能及性能要求挑选合适的IO流&#xff0c;如图所示&#xff0c;为Java中IO流类的体系。 从上图发现&#xff0c;很多流都是成对出现的&#xff0c;比如&#xff1a; FileInputStream/FileOutputStream&#xff0…

vue3的api风格

Vue的组件有两种不同的风格&#xff1a;组合式API 和 选项式API 选项式api 选项式API&#xff0c;可以用包含多个选项的对象来描述组件的逻辑&#xff0c;如&#xff1a;data&#xff0c;methods&#xff0c;mounted等。 组合式api setup&#xff1a;是一个标识&#xff0c;告…