【网络通信】TCP三次握手、四次挥手

TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。在TCP/IP协议族中,TCP协议负责在两个网络节点之间建立可靠的连接,并保证数据包的顺序传输和数据的完整性。

 

1.TCP三次握手

TCP三次握手(Three-way Handshake)是TCP/IP协议中用于建立TCP连接的过程。这个过程确保了两个通信节点的初始化序列号(ISN)是同步的,同时也交换了彼此的初始窗口大小等参数。三次握手的过程如下:

  1. 第一次握手(SYN)

    • 客户端发送一个SYN(同步序列编号)标志的TCP段,以便开始一个新的连接。这个段中包含客户端的初始序列号(client_isn)。
  2. 第二次握手(SYN-ACK)

    • 服务器接收到客户端的SYN请求后,需要确认客户端的SYN,同时自己也发送一个SYN请求。服务器在响应中包含它自己的初始序列号(server_isn),并将确认序号设置为客户端的初始序列号加1,即client_isn + 1
  3. 第三次握手(ACK)

    • 客户端收到服务器的SYN-ACK响应后,再次发送一个确认响应,这个响应中包含确认序号,设置为服务器的初始序列号加1,即server_isn + 1

完成三次握手后,TCP连接就建立成功了,接下来就可以开始数据的传输了。

这个握手过程保证了双方都知道对方已经准备好接收和发送数据,同时也防止了因网络中遗留的、失效的连接请求而错误地建立连接。

在代码中实现TCP三次握手通常不需要手动编写底层的网络通信代码,因为TCP三次握手是由操作系统和网络协议栈自动完成的。当你使用高级编程语言(如Python、Java、C++等)中的套接字(Socket)库时,底层的TCP握手过程是由操作系统负责的。

在C语言中,使用套接字API(通常称为BSD套接字API)可以实现TCP客户端和服务器。以下是一个简单的例子,展示了如何在C语言中实现TCP服务器和客户端。

TCP服务器 (server.c):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>int main() {int server_fd, new_socket;struct sockaddr_in address;int opt = 1;int addrlen = sizeof(address);char buffer[1024] = {0};const char* hello = "Hello from server";// 创建socket文件描述符if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {perror("socket failed");exit(EXIT_FAILURE);}// 绑定socket到地址if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {perror("setsockopt");exit(EXIT_FAILURE);}address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY;address.sin_port = htons(8080);if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {perror("bind failed");exit(EXIT_FAILURE);}// 监听是否有客户端连接if (listen(server_fd, 3) < 0) {perror("listen");exit(EXIT_FAILURE);}// 接受客户端连接if ((new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen)) < 0) {perror("accept");exit(EXIT_FAILURE);}// 读取数据read(new_socket, buffer, 1024);printf("Message from client: %s\n", buffer);// 发送数据send(new_socket, hello, strlen(hello), 0);printf("Hello message sent\n");// 关闭连接close(new_socket);close(server_fd);return 0;
}

TCP客户端 (client.c):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>int main() {int sock = 0;struct sockaddr_in serv_addr;const char* hello = "Hello from client";char buffer[1024] = {0};// 创建socket文件描述符if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {printf("\n Socket creation error \n");return -1;}serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(8080);// 将IPv4地址从文本转换为二进制形式if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {printf("\nInvalid address/ Address not supported \n");return -1;}// 连接到服务器if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {printf("\nConnection Failed \n");return -1;}// 发送数据send(sock, hello, strlen(hello), 0);printf("Hello message sent\n");// 读取数据read(sock, buffer, 1024);printf("Message from server: %s\n", buffer);// 关闭连接close(sock);return 0;
}

在上述代码中,服务器和客户端都使用套接字API来创建TCP连接。服务器首先创建一个套接字并绑定到指定的地址和端口,然后监听是否有客户端连接。客户端创建一个套接字并连接到服务器的地址和端口。连接成功后,双方可以通过套接字发送和接收数据。

要编译和运行这些程序,你需要有一个C编译器,如GCC。可以使用以下命令编译服务器和客户端:gcc -o server server.c    gcc -o client client.c

然后,首先运行服务器:./server

在另一个终端中运行客户端:./client

客户端和服务器将通过TCP三次握手建立连接,然后客户端发送一个消息给服务器,服务器回复一个消息给客户端,最后双方关闭连接。

 

2.TCP四次挥手

TCP四次挥手(Four-way Handshake)是TCP/IP协议中用于终止一个TCP连接的过程。当一个连接的双方完成数据传输后,它们需要通过四次挥手来优雅地关闭连接。这个过程确保了所有在传输中的数据都被正确地处理,并且双方都同意断开连接。

四次挥手的过程如下:

  1. 第一次挥手(FIN)

    • 连接的一端(假设是客户端)发送一个FIN(结束)标志的TCP段,表示它已经完成发送数据,并希望关闭到另一端(服务器)的连接。
  2. 第二次挥手(ACK)

    • 服务器接收到这个FIN请求后,发送一个ACK(确认)响应,确认序号为收到FIN的序号加1。此时,服务器仍然可以发送数据,但客户端不再发送数据。
  3. 第三次挥手(FIN)

    • 一段时间后,服务器也完成了数据发送,发送一个FIN段给客户端,请求关闭连接。
  4. 第四次挥手(ACK)

    • 客户端收到服务器的FIN请求后,发送一个ACK响应,确认序号为收到服务器FIN的序号加1。在发送完这个ACK后,客户端会等待足够长的时间(通常是2倍的最大段生命周期MSL),以确保服务器收到确认包。

完成四次挥手后,TCP连接就正式关闭了。在这个过程中,每个方向的连接都是独立关闭的,这就是为什么需要四个步骤来完全终止连接。

需要注意的是,在四次挥手过程中,主动关闭连接的一端(如客户端)在发送完最后一个ACK后进入TIME_WAIT状态,而不是立即关闭连接。这是为了确保对方能够收到最后的ACK确认包,如果对方没有收到,会重新发送FIN请求。TIME_WAIT状态持续的时间通常是2倍的最大段生命周期MSL,这是一个保守的等待时间,确保在网络中遗留的TCP段都已经过期。

 

TCP连接中如何处理同时的双向关闭?

在TCP连接中,如果双方同时发送FIN包来关闭连接,这种情况被称为同时关闭(Simultaneous Close)。这种情况下,四次挥手的过程会稍微有所不同,但基本的原理是相同的:确保双方都同意关闭连接,并且所有在传输中的数据都被正确地处理。

同时关闭的过程如下:

  1. 双方同时发送FIN包

    • 连接的双方都发送一个FIN包给对方,表示自己已经完成了数据的发送,并希望关闭连接。
  2. 双方同时接收对方的FIN包,并回应ACK

    • 每一方收到对方的FIN包后,发送一个ACK包作为响应。这时,每个方向上的数据传输都已经关闭,但是双方都还在等待对方的最终确认。
  3. 双方再次发送ACK包

    • 在接收到对方的ACK包后,每一方都再次发送一个ACK包作为最终确认。这个ACK包的目的是确认对方的FIN包,以及告知对方自己的ACK包已经被接收。
  4. 双方关闭连接

    • 在发送完最后一个ACK包后,双方都可以关闭连接。在关闭连接之前,每一方都会等待足够长的时间(通常是2倍的最大段生命周期MSL),以确保对方能够收到最后的ACK包。

在同时关闭的情况下,连接的双方都会进入TIME_WAIT状态,以确保所有的TCP段都已经过期,从而避免了旧的连接信息干扰新的连接。TIME_WAIT状态对于防止网络中的旧连接信息(例如延迟的TCP段)对后续连接造成影响是非常重要的。

在实际的网络编程中,同时关闭的情况并不常见,因为通常一方(如客户端)会主动发起关闭,而另一方(如服务器)则会响应这个关闭请求。然而,了解同时关闭的处理方式对于理解TCP协议的完整性和健壮性是很有帮助的。

 

在四次挥手过程中,如果网络出现问题,应该如何处理?

在TCP四次挥手过程中,如果网络出现问题,TCP协议提供了多种机制来处理这些情况,确保连接能够可靠地关闭。以下是一些可能的问题及其处理方式:

  1. 丢失FIN包

    • 如果一方发送的FIN包在网络上丢失,发送方会等待接收方的ACK确认。如果在一定时间内没有收到确认,发送方会重新发送FIN包。
  2. 丢失ACK包

    • 如果一方发送的ACK包在网络上丢失,接收方会等待对方的下一个TCP包。如果对方也处于等待状态,那么双方可能会陷入死锁。为了解决这个问题,TCP使用了一个超时重传机制,发送方在等待ACK超时后会重新发送FIN包。
  3. 连接中的一方崩溃

    • 如果连接中的一方崩溃,另一方将不会收到预期的ACK包。在这种情况下,发送方会重传FIN包,但由于对方已经崩溃,重传不会得到响应。最终,发送方会认为对方已经关闭,并在超时后关闭自己的连接。
  4. 网络分区

    • 如果网络分区导致双方无法通信,每一方都可能认为对方已经崩溃。在这种情况下,每一方都可能开始关闭连接的过程,但由于无法通信,四次挥手无法完成。当网络恢复时,可能会出现重复的FIN包和ACK包,但TCP协议能够处理这种情况,确保连接最终能够正确关闭。
  5. 延迟的TCP段

    • 在连接关闭后,如果网络中仍然有延迟的TCP段,这些段可能会干扰后续的连接。为了防止这种情况,TCP在关闭连接后进入TIME_WAIT状态,等待足够长的时间以确保所有的TCP段都已经过期。

TCP协议的设计考虑了网络的不可靠性,并通过上述机制来确保连接的可靠性。这些机制包括超时重传、序列号和确认号的使用、以及TIME_WAIT状态等。因此,即使在网络出现问题的情况下,TCP仍然能够尽可能地保证连接的正确关闭。

 

在TCP连接关闭过程中,如何处理并发的多个连接请求?

在TCP连接关闭过程中,服务器通常需要处理并发的多个连接请求。这是通过多线程或多进程技术来实现的,允许服务器同时处理多个客户端的连接和关闭请求。以下是一些处理并发连接请求的方法:

  1. 多线程

    • 服务器可以为每个新的连接创建一个线程。当客户端连接到服务器时,服务器接受连接并创建一个新的线程来处理该连接。这样,每个连接都有自己的线程,可以在独立的上下文中进行通信和关闭。
  2. 多进程

    • 类似于多线程,服务器可以为每个连接创建一个新的进程。这种方法在操作系统级别提供了隔离,但相对于多线程,进程之间的通信开销更大。
  3. 非阻塞IO和事件驱动

    • 使用非阻塞IO和事件驱动的编程模型,如使用epoll(Linux)、kqueue(BSD)、IOCP(Windows)等,可以允许服务器在一个线程或进程中处理多个连接。这种模型通过在事件发生时(如数据到达、连接建立或关闭)进行回调,从而实现高效的并发处理。
  4. 线程池或进程池

    • 为了避免频繁创建和销毁线程或进程的开销,服务器可以使用线程池或进程池。预先创建一定数量的线程或进程,然后将它们分配给新的连接。这种方法可以平衡资源使用和性能。
  5. 异步IO

    • 异步IO允许服务器发起IO操作(如接收数据、发送数据、接受连接等)而无需等待操作完成。这样,服务器可以在单个线程或进程中处理多个连接,而不会因为等待IO操作而阻塞。

在处理并发的多个连接请求时,服务器还需要维护连接的状态,确保每个连接的正确关闭。这通常涉及到连接池的管理、连接超时的处理、以及异常情况下的资源清理等。

总之,处理并发的多个连接请求需要服务器具备高效的网络IO模型和资源管理策略。选择合适的方法取决于服务器的具体需求、性能目标以及运行环境。

 

结语

以上就是TCP三次握手,四次挥手的知识,本次分享到此结束。

最后的最后,还请大家点点赞,点点关注,谢谢大家!

 

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

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

相关文章

【工具】录屏软件Captura安装使用及ffmpeg下载配置

开启技术视频创作&#xff0c;录屏软件林林总总&#xff0c;适合的、习惯的最好。 录屏软件Captura的使用及ffmpeg下载配置 1.Captura下载、安装2.FFmpeg下载、配置3.Captura屏幕录制试用、录制视频效果 1.Captura下载、安装 Captura主要是一个免费开源的录屏软件&#xff0c…

系统架构设计精华知识

数据流风格&#xff1a;适合于分阶段做数据处理&#xff0c;交互性差&#xff0c;包括&#xff1a;批处理序列、管理过滤器。调用/返回风格&#xff1a;一般系统都要用到&#xff0c;包括&#xff1a;主程序/子程序&#xff0c;面向对象&#xff0c;层次结构&#xff08;分层越…

20240330-1-词嵌入模型w2v+tf-idf

Word2Vector 1.什么是词嵌入模型&#xff1f; 把词映射为实数域向量的技术也叫词嵌⼊ 2.介绍一下Word2Vec 谷歌2013年提出的Word2Vec是目前最常用的词嵌入模型之一。Word2Vec实际是一种浅层的神经网络模型&#xff0c;它有两种网络结构&#xff0c;分别是连续词袋&#xff…

54位大咖演讲精华! 中国生成式AI大会圆满收官,TOP50企业榜单揭晓

54位大咖演讲精华&#xff01; 中国生成式AI大会圆满收官&#xff0c;TOP50企业榜单揭晓© 由 红板报 提供 智东西4月19日报道&#xff0c;为期两天的2024中国生成式AI大会&#xff0c;今日在京圆满收官。 54位产学研投嘉宾代表全程干货爆棚&#xff0c;报名咨询人数逾52…

操作符不存在:sde.st_geometry ^ !sde.st_geometry建议 SQL函 数st_intersects在内联inlining期间

操作符不存在&#xff1a;sde.st_geometry ^ &#xff01;sde.st_geometry建议 SQL函 数st_intersects在内联inlining期间 问题&#xff1a;最近在使用SQL图形处理函数处理图形时&#xff0c;莫名奇妙报如下错误&#xff0c;甚是费解 于是开始四处"寻医问药" 1、nav…

G1、CMS垃圾回收期专题

共同点 非阻塞 使用三色标记法 初始标记、并发标记、重新标记、并发清理 &#xff08;初始标记、重新标记需要stop world&#xff09; CMS垃圾回收器 缺点 浮动垃圾 有垃圾碎片 关注停顿时间&#xff0c;使用了效率最高的标记清除算法 G1垃圾回收器 缺点 需要配置高&…

MySQL表级锁——技术深度+1

引言 本文是对MySQL表级锁的学习&#xff0c;MySQL一直停留在会用的阶段&#xff0c;需要弄清楚锁和事务的原理并DEBUG查看。 PS:本文涉及到的表结构均可从https://github.com/WeiXiao-Hyy/blog中获取&#xff0c;欢迎Star&#xff01; MySQL表级锁 MySQL中表级锁主要有表锁…

【Java EE】 SpringBoot配置文件

文章目录 &#x1f340;配置文件的作用&#x1f334;SpringBoot配置文件&#x1f343;配置文件的格式&#x1f333;properties 配置文件说明&#x1f338;properties基本语法&#x1f338;读取配置文件&#x1f338;properties 缺点分析 &#x1f332;yml 配置文件说明&#x1…

Docker基本管理和虚拟化

一、docker的发展历史 https://www.cnblogs.com/rongba/articles/14782624.htmlhttps://www.cnblogs.com/rongba/articles/14782624.html 二、docker的概述 Docker是一个开源的应用容器引擎&#xff0c;基于go语言开发并遵循了apache2.0协议开源。 Docker是在Linux容器里运行…

centos7 Nginx一键安装自动化脚本

离线环境下 centos7 Nginx一键安装自动化脚本 本文介绍了一个 Bash 脚本&#xff0c;可用于自动化安装 Nginx 服务器。该脚本简化了安装过程&#xff0c;省去了手动配置的繁琐步骤。 脚本功能特点&#xff1a; 依赖检查和安装&#xff1a; 自动检查并安装 Nginx 所需的依赖包…

轨迹跟踪控制导读

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言一、小车底盘运动学模型介绍二、路径跟踪方法&#xff1a;PID控制算法实现路径跟踪--飞思卡尔的方法三、路径跟踪方法&#x…

附近商户-GEO数据结构的基本用法

10、附近商户 10.1、附近商户-GEO数据结构的基本用法 GEO就是Geolocation的简写形式&#xff0c;代表地理坐标。Redis在3.2版本中加入了对GEO的支持&#xff0c;允许存储地理坐标信息&#xff0c;帮助我们根据经纬度来检索数据。常见的命令有&#xff1a; GEOADD&#xff1a…

SpringBoot Bean管理(扫描、注册、注册条件)

Bean扫描 一般的扫描包路径 需要使用xml标签或者是ComponentScan(basePackages “xxx.xxx”) ,但是在SpringBoot中不需要。 在springBoot 项目的启动类中有一个注解&#xff1a;SpringBootApplication,这个注解包含以下注解&#xff1a; 但是ComponentScan并没有指明包路径…

开源协议的对比和商业上的安全使用

开源协议的对比和商业上的安全使用 开源组件是&#xff1a;“任何人都可以自由使用、更改和共享&#xff08;以修改或未修改的形式&#xff09;的软件”。当今企业依靠开源来加速开发、降低成本和推动创新。对开放源码的糟糕管理可能会使组织面临安全、法律和操作风险。 使用…

Maven基础篇5

私服 私服目的&#xff0c;方便公司内计算机通信&#xff0c;方便程序员们开发时资源互换&#xff1b; 1.Nexus私服 https://help.sonatype.com/repomanager3/download 可下载&#xff0c;第一个是服务器&#xff0c;第二个是工作空间 bin中有可执行命令 nexus.exe/run端口…

比亚迪唐EV和唐DM-p荣耀版上市,成为新能源汽车市场中的佼佼者!

随着环保理念的深入人心&#xff0c;新能源汽车市场正迎来前所未有的发展机遇。在这个变革的浪潮中&#xff0c;唐EV和唐DM-p荣耀版的上市无疑为市场注入了新的活力。它们凭借先进的技术、卓越的性能以及豪华配置&#xff0c;成为了新能源汽车市场中的佼佼者。然而&#xff0c;…

【飞桨AI实战】人体姿态估计:零基础入门,从模型训练到应用开发

前言 本次分享将带领大家从 0 到 1 完成一个人体姿态估计任务&#xff0c;覆盖数据准备、模型训练、推理部署和应用开发的全流程&#xff0c;项目将采用以PaddlePaddle为核心的飞桨深度学习框架进行开发&#xff0c;并总结开发过程中踩过的一些坑&#xff0c;希望能为有类似项…

前端面试真题

vue 1、说一下你对vue生命周期的理解 组件从创建到销毁的过程就是它的生命周期 beforeCreat&#xff1a;在这个阶段属性和方法都不能使用 created&#xff1a;这里是实例创建完成之后&#xff0c;在这里完成了数据监测&#xff0c;可以使用数据&#xff0c;修改数据&#xff…

增加PyQt5界面的交通流量预测(模型为CNN_GRU,CNN_BiGRU_ATTENTION,LSTM,Python代码)

1.效果视频&#xff1a;增加PyQt5界面的交通流量预测&#xff08;模型为CNN_GRU&#xff0c;CNN_BiGRU_ATTENTION&#xff0c;LSTM&#xff09;_哔哩哔哩_bilibili&#xff09; 2.三个模型和数据集的介绍 交通流量预测(python代码&#xff0c;压缩包中带有数据&#xff0c;CN…

曲线救国|基于函数计算FC3.0部署AI数字绘画stable-diffusion

曲线救国|基于函数计算FC3.0部署AI数字绘画stable-diffusion 基于函数计算FC2.0部署AI数字绘画stable-diffusion基于函数计算FC3.0部署AI数字绘画stable-diffusion总结 在经过了上一次曲线救国失败经历之后&#xff0c;失败经历参考博文&#xff1a;https://developer.aliyun.c…