当前位置: 首页 > article >正文

(C语言)网络编程之TCP(含三次握手和四次挥手详解)

一、概述

TCP(Transmission ControlProtocol) : 传输控制协议,是一个 面向连接的、可靠的、基于字节流 的传输层的协议。TCP协议建立的是一种点到点的,一对一的可靠连接协议

特点
数据无丢失
数据无失序
数据无错误
数据无重复

使用场景
----适合于对传输质量要求较高,以及传输大量数据的通信。
----在需要可靠数据传输的场合,通常使用TCP协议
----MSN/QQ等即时通讯软件的用户登录账户管理相关的功能通常采用TCP协议
----面向连接,数据可靠
----三次握手,本意指TCP/IP协议栈中,要求TCP协议提供可靠的连接服务。我们需要建立可靠的、稳定的连接的时候,我们就需要使用三次握手。它的实质是指建立一个TCP连接的时候,客户端和服务端需要发送3个数据包。
----四次挥手,当用户想要断开连接的时候,需要发送四次数据包,才会中断连接。

二、TCP数据包报文结构

图片来源:TCP的报文详细解读
在这里插入图片描述

  1. 源端口
    指发送方计算机发送数据的出来的那个端口号
  2. 目的端口
    目的端口同理,指的是接收方计算机所接收数据的那个端口
  3. 序号(seq)
    seq号,我们知道一个数据可能是由多个数据包组成,序号的作用就是来标识各个数据包的先后顺序,序号占32bit,那么序号最多有2的32次方-1个,那假如超过了这个数怎么办呢?就从0开始重新编号,这个seq号比较重要,后面的三次握手的内容需要用到
  4. 确认号(ack)
    ack号,注意ack号和下面的ACK标识是不一样的,ack=seq+1时说明发送方和接收方配对成功了。这个确认号是数据接收方反馈给发送方的一个属性,假如确认号为N,那么表示接收方已经接收到了N-1及其以前的数据
  5. 数据偏移
    这个数据偏移是针对TCP报文段来说的,指的是从TCP报文段到TCP数据部分之间的距离,也就是TCP首部的大小,一般来说是20个字节,但是我们从图中可以发现第六行有个可变长度,所以有的时候其不是20个字节。
  6. 保留
    保留表示现在没有被使用,这段长度是可以被使用的。
  7. URG
    URG=1时表示此报文为紧急报文,所以这个报文优先级最高,会被发送方放到最开头传输,需配合我们下面要说到的紧急指针一起使用
  8. ACK
    ACK是用来指明连接是否建立的属性,当ACK=1时说明连接已经建立了,建立连接后的所有报文ACK都必须为1,并且规定只有当ACK=1时确认号才会有效
  9. PSH
    这个属性是用于一端的应用进程希望在键入一个命令后立即就能收到对方的响应时使用,TCP可进行推送操作
  10. RST
    这个字段其实就是reset,当我们的TCP连接出现严重错误时,我们需要将连接进行重置,这时候需要释放连
    接,重新建立新的连接
  11. SYN
    在建立连接时使用,用来同步序号:当 SYN=1,ACK=0 时,表示这是一个请求建立连接的报文段;当SYN=1,ACK=1 时,表示对方同意建立连接;SYN=1 时,说明这是一个请求建立连接或同意建立连接的报文;
    只有在前两次握手中 SYN 才为 1
  12. FIN:
    此属性用于释放连接,是finnish的缩写,当发送方将FIN置1时,说明数据已经完全发送完毕,要求释放连接
  13. 窗口:
    占 16 位;它表示从 Ack Number 开始还可以接收多少字节的数据量,也表示当前接收端的接收窗口还有多少剩余空间。该字段可以用于 TCP 的流量控制。
  14. 校验和:
    占 16 位;它用于确认传输的数据是否有损坏。发送端基于数据内容校验生成一个数值,接收端根据接收的数据校验生成一个值。两个值必须相同,才能证明数据是有效的。如果两个值不同,则丢掉这个数据包。
    Checksum 是根据伪头 + TCP 头 + TCP 数据三部分进行计算的。
  15. 紧急指针:
    当URG=1时,说明此报文为紧急报文,紧急指针指出本报文中紧急数据的字节数,紧急数据处理完毕TCP会告诉应用程序恢复正常工作,并且,窗口为0时也可以发送紧急数据

三、三次握手和四次挥手

(一)、三次握手

概述:三次握手(Three-way Handshake)其实就是指建立一个TCP连接时,需要客户端和服务器总共发送3个数据包。进行三次握手的主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备,确认连接的建立

机理
第一次握手:证明客户端的发送能力正常
第二次握手:证明服务器端的接收能力、发送能力正常
第三次握手:证明客户端的接收能力正常

具体过程
在这里插入图片描述

  1. 第一次握手,由客户端发送请求连接即SYN = 1,TCP规定SYN=1的时候,不能够携带数据。但是需要消耗一个seq序号。因此,产生了一个序号seq = x。
  2. 第二次握手,B主机收到A主机发送的消息。向A主机发送确认。发送SYN = 1,表示请求连接已经收到,把TCP包中ACK位置为1,表示同意连接,并发送一个新的序列号seq =y,确认好ack = x + 1;
  3. 第三次握手,其实经过两次连接之后,双方的基本连接已经建立。但是A收到B的确认之后,还需要向B给出确认,说明自己已经收到确认包了。设置确认ACK = 1,ack = y + 1。而顺序号seq = x + 1。双方建立稳定的连接。此时ACK报文可以携带数据。

(二)、四次挥手

概述:所谓四次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发

具体过程:

在这里插入图片描述
第一次挥手 :
客户端打算关闭连接,此时会发送⼀个 TCP ⾸部 FIN 标志位被置为 1 的报⽂ ,也即 FIN 报文,之后客户端进⼊ FIN_WAIT_1 状态。
第二次挥手:
服务端收到该报⽂后,就向客户端 发送 ACK 应答报⽂ ,接着服务端进⼊ CLOSED_WAIT 状态。
第三次挥手 :
客户端收到服务端的 ACK 应答报⽂后,之后进⼊ FIN_WAIT_2 状态。但此时服务端可能还有一些数据未处理完。 等待服务端处理完数据后,也向客户端发送 FIN 报⽂ ,之后服务端进⼊LAST_ACK 状态。
第四次挥手 :
客户端收到服务端的 FIN 报⽂后,回⼀个 ACK 应答报⽂,之后进⼊ TIME_WAIT 状态服务端收到了 ACK 应答报⽂后,就进⼊了 CLOSED 状态,⾄此服务端已经完成连接的关闭。
客户端在经过 2MSL ⼀段时间后,⾃动进⼊ CLOSED 状态,⾄此客户端也完成连接的关闭。

相关概念解释
ESTABLISHED:代表当前TCP已经连接成功
MSL(Maximum Segment Lifetime),指一个片段在网络中最大的存活时间。2MSL就是一个发送和一个回复所需的最大时间。
FIN_WAIT_1:等待对方的FIN报文。
FIN_WAIT_2:待对方的FIN报文。
TIME_WAIT:示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了
CLOSE_WAIT:种状态的含义其实是表示在等待关闭
LAST_ACK:个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。

当收到ACK报文后,也即可以进入到CLOSED可用状态了。

QA:
为什么客户端要等待2MSL?
主要原因是为了保证客户端发送的ACK报文能到服务器,因为这个ACK报文可能丢失,并且2MSL是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃,这样新的连接中不会出现旧连接的请求报文。

握手三次原因:
主要原因:防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。
TCP 三次握手的设计核心在于双向通信确认防止历史连接干扰

如果采用两次握手会出现以下情况:
客户端向服务器端发送的请求报文由于网络等原因滞留,未能发送到服务器端,此时连接请求报文失效,客户端会再次向服务器端发送请求报文,之后与服务器端建立连接,当连接释放后,由于网络通畅了,第一次客户端发送的请求报文又突然到达了服务器端,这条请求报文本该失效了,但此时服务器端误认为客户端又发送了一次连接请求,两次握手建立好连接,此时客户端忽略服务器端发来的确认,也不发送数据,造成不必要的错误和网络资源的浪费。

挥手四次原因:
释放资源时,接受方在收到发送方的释放连接请求后,还需要一段时间来处理未完成的发送请求,这里需要两次确认发送方的请求:第一次是未处理完,我还不能释放,但是收到了你的请求,告诉发送方一声,等等我;第二次确认表示已经处理完请求了,我也可以进行释放了。因此需要四次


http://www.kler.cn/a/612070.html

相关文章:

  • 适配器模式及其典型应用
  • Vue-create-vue-开发流程-项目结构-API风格-ElementPlus-入门准备工作
  • 【保姆级别教程】VMware虚拟机安装Mac OS15苹果系统附带【VMware TooLS安装】【解锁虚拟机】和【Mac OS与真机共享文件夹】手把手教程
  • 分布式共识算法解密:从Paxos到Raft的演进之路
  • 使用string和string_view(一)——C风格字符串、字符串字面量和std::string
  • 批量将 PDF 转换为 Word/PPT/Txt/Jpg图片等其它格式
  • 开发DOM更新算法
  • [python]基于yolov8实现热力图可视化支持图像视频和摄像头检测
  • CentOS 7安装 mysql
  • 老是忘记package.json,备忘一下 webpack 环境下 Vue Cli 和 Vite 命令行工具对比
  • 【Pandas】pandas Series to_xarray
  • SpringBoot集成腾讯云OCR实现身份证识别
  • 【牛客网】数据分析笔试刷题
  • Charles抓HTTPS包
  • 数据结构:汉诺塔问题的递归求解和分析
  • 部分 Bash 内置命令的详解
  • 企业网站源码HTML成品网站与网页代码模板指南
  • 学习记录-Ajax-自封装axios函数
  • RAMS(区域大气建模系统)评估土地利用/覆被变化的气候与水文效应
  • 【Django】教程-3-数据库相关介绍