IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 关于TCP三次握手和两次握手的思考 -> 正文阅读

[网络协议]关于TCP三次握手和两次握手的思考

关于TCP三次握手和两次握手的思考

TCP连接需要握手的原因

TCP协议是一个非常常见的全双工协议,它保证了数据的可靠传输。

使用TCP服务的程序一般需要三次握手来建立TCP的连接,根据RFC文档可知,TCP三次握手主要是让发送方和接收方知道各自的序列号,利用序列号来维护数据的可靠传输。

TCP协议三次握手流程如下:
seq表示序列号,ack表示应答号,ack = y表示该机器希望下次接收来的序列号为y,SYN = 1表示这是一个建立序列号同步的过程,ACK = 1表示这是一个应答消息
客户端随机生成一个序列号seq = x,向服务端发送该请求(SYN = 1,seq = x, ACK = 0, ack = ?)
服务端接收到客户端的请求之后,同样生成一个随机序列号seq = y,向客户端发送应答及其序列号(SYN = 1, seq = y, ACK = 1, ack = x+1)
客户端接收到接收的消息之后,向服务端发送一个应答消息(SYN = 0, seq = x+1,ACK = 1,ack = y+1)

在第一次,第二次握手中,是不允许携带数据的,而SYN = 1表示默认消耗一个数据,所以第二次握手中消息中的ack = x+1。
而第三次握手一般是不携带数据的,所以三次握手后客户端向服务端发送的第一个消息的seq = x+1

两次握手的可行性分析

但是为什么是三次握手而不是两次呢?经过两次握手之后发送方和接收方已经知道了双方的序列号了,是不是已经可以实现同步了?这是一个网络上很多人讨论的问题,以下我的一些分析,不保证对,希望大家一起讨论。

我们可以假设TCP握手协议只有两次:
客户端随机生成一个序列号seq = x,向服务端发送该请求(SYN = 1,seq = x, ACK = 0, ack = ?)
服务端接收到客户端的请求之后,同样生成一个随机序列号seq = y,向客户端发送应答及其序列号(SYN = 1, seq = y, ACK = 1, ack = x+1)

分析一个成功的场景:
客户端向服务端进行第一次握手,服务端向客户端发送应答并发送自己的序列号
此时,客户端因为已经接受到服务端的应答,所以可以确定自己的序列号已经被服务端知道,所以它下一步可以发送实际的数据了
而服务端向客户端发送了应答,它默认客户端已经知道了自己的序列号,所以分配连接的资源,等待客户端的下一个数据
若一切运行良好,客户端下一步向服务端发送大小为9的数据(SYN = 0,seq = x+1,ACK = 0, ack = y+1)
服务端接收后向客户端发送回应(SYN = 0, seq = y+1, ACK = 1, ack = x+11)

上面是运行良好的情况,但是网络中丢包现象是极为普遍的,我们可以再假设以下的情景
1.客户端发送成功了,接收端的应答丢失
此时客户机的状态:第一次握手请求(SYN = 1,seq = x, ACK = 0, ack = ?)迟迟没有回应,认为握手请求丢失,重传握手请求
服务器的状态为:已经为客户端分配了资源,等待客户端的第一条消息(期待消息的序列号为seq = x+1)。但此时接收到的消息为(SYN = 1,seq = x, ACK = 0, ack = ?),可以再次发送一次应答信号(SYN = 1, seq = y, ACK = 1, ack = x+1),并期待这次连接成功
若这次没有产生丢包,则可以进行正常的TCP通信了

2.客户端发送的第一次的消息在网络中发生了延时,再次发送第二次消息,此时,先后两次握手陆续到达,请求连接,服务端应答消息正常抵达客户端
此时客户机状态,两条连接请求都成功,但客户端会认为只有第二条请求成功
服务器状态:服务器接收到第一条握手请求后,分配相应资源,发送应答消息,之后再次接收到一个相同客户端的第一次握手请求
这时会出现两种情况:1.服务端有能力区分这两种请求是来自同一个客户端的相同请求,将第二次到来的握手请求丢弃处理。2.服务器没有能力区分这两种请求是来自于同一个客户端的相同请求,同样为这条请求分配资源,等待客户端的应答
若是第二种情况呢,虽然最后服务器到达一定时间后会自动断开TCP连接,收回资源,但是也造成了比较大的资源浪费。(不过这样或许能减少一些网络的流量?)
对于第一种情况呢,服务端分辨是否为同一请求有三个重要参考条件(端口号,IP,SYN = 1时的seq)
从我们可以在一个浏览器中开两个网页访问同一个网站,可以看出根据前两个条件服务端无法做出区分
接下来分析seq的情况,我们假设客户端重发握手请求时与前一次都是相同的seq,这样服务端或许就可以根据此消息中的同一个端口号,IP,seq判断出是同一个握手请求了(再加一个标志位或许可以不利用seq解决这种浪费资源的情况?)。

3.第三种思考是从TCP是一个全双工的协议来看的。我们之前的思考都是建立在TCP连接后客户端先主动向服务端发送消息。当然,实际我并没有想到什么服务端先向客户端发送数据的例子
若是有需要建立连接后服务端先向客服端发送消息的情况呢?
经过以下流程
两次握手都运行良好
客户端随机生成一个序列号seq = x,向服务端发送该请求(SYN = 1,seq = x, ACK = 0, ack = ?)
服务端接收到客户端的请求之后,同样生成一个随机序列号seq = y,向客户端发送应答及其序列号(SYN = 1, seq = y, ACK = 1, ack = x+1)
此时服务端的状态 :准备发送一个序列号为y+1的数据(根据默认协议)
此时客户端的状态:准备接收一个序列号为y+1的数据
若是服务端发送的应答信息产生了丢包呢,此时服务端想要发送一个序列号为y+1的数据,但是客户端并不知道服务端的序列号。
此时就出现了无法解决的的错误
当然,由于博主学识有限,并未想到有关于服务端先向客服端发送协议的情况

这样分析之后,握手两次或许可行,不过,由于第2,3种情况的原因,再加上TCP的收到消息就给出应答的机制,或许还有一些博主没想到的方面,TCP最终选择了三次握手。毕竟,3次握手肯定比2次握手来得更为可靠。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-08-03 11:34:09  更:2021-08-03 11:34:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/4 1:04:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码