【网络通信】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.mfbz.cn/a/569822.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

汇编期末复习知识点

参考文献1 第一章 概述 组成 计算机系统由硬件子系统和软件子系统组成。硬件子系统&#xff1a;组成计算机系统的所有电子的&#xff0c;机械的&#xff0c;光学的和磁性的元部件。 计算机中常用进制数表示 十进制(Decimal):数据尾部加一后缀D&#xff0c;如2355D二进制&a…

FANUC机器人socket通讯硬件配置

一、添加机器人选配包 Fanuc机器人要进行socket通讯&#xff0c;需要有机器人通讯的选配包&#xff0c;1A05B-2600-R648 User Socket Msg&#xff0c;1A05B-2600-R632 KAREL&#xff0c;1A05B-2600-R566 KAREL Diagnostic&#xff0c;1A05B-2600-J971 KAREL Use Sprt FCTN。 二…

初学python,怎样入门?

答案&#xff1a;乌龟绘图。 "乌龟绘图"通常指的是使用Logo语言的变种——Python中的turtle模块来进行图形绘制。在turtle模块中&#xff0c;一只名为“海龟”&#xff08;Turtle&#xff09;的小动物会在屏幕上移动&#xff0c;根据其行进路径来绘制图形。以下是一段…

音视频直播原理解析

直播原理就是一个推流和拉取流的过程&#xff1b; 直播端将直播流推送至服务器&#xff0c;用户端发起请求从服务器拉取直播流然后解码播放 第一部分就是视频直播端的操作&#xff1a;视频采集处理后推流到流媒体服务器。 首先从前端采集设备中获得原始的音频、视频数据&…

Vue页面生成导出PDF文件

第一种&#xff1a; 使用浏览器自带打印方法window.print(); 也可使用print-js插件&#xff08;原理相同&#xff09; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>printDemo</title> </…

助力24五一杯数学建模比赛

完成助力美赛建模&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 完成助力妈妈杯建模&#xff01;&#xff01;&#xff01;&#xff01; 完成助力华中杯建模&#xff01;&#xff01;&#xff01;&#xff01; 这边将在开赛后24小时内发布资料和初步思路 需…

系统思考—啤酒游戏

最近有不少的合作伙伴来询问我啤酒游戏这个来自于MIT&#xff08;麻省理工学院&#xff09;经典的沙盘&#xff0c;上周刚刚结束Midea旗下的一家公司市场运营部《啤酒游戏沙盘-应对动态性复杂的系统思考智慧》的课程。 参与这次沙盘体验的团队成员深刻体会到了全局思考的重要性…

【SpringBoot实战篇】获取用户详细信息-ThreadLocal优化

1 分析问题 对token的解析当初在拦截器中已经写过。期待的是在拦截器里写了&#xff0c;在其他地方就不写了&#xff0c;应该去复用拦截器里面得到的结果 2 解决方式-ThreadLocal 2.1提供线程局部变量 用来存取数据: set()/get()使用ThreadLocal存储的数据, 线程安全 2.2过程图…

【leetcode面试经典150题】71. 对称二叉树(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

Android Studio XML 预览View 底部移动到右边

以前 XML 的预览都是在右边的&#xff0c;最近不知道为什么突然到下面去了&#xff0c;很不习惯 找半天想把 预览view 移动到右边&#xff0c;一直没找到按钮。 误打误撞移回来了&#xff0c;原来只要再点击一次 split&#xff0c;就可以变动位置了&#xff0c;记录一下。

冶金电镀大电流测量BR罗氏线圈电流变送器

安科瑞薛瑶瑶18701709087 BR 系列产品应用电磁感应原理&#xff0c;对电网中的交流大电流进行实时测量&#xff0c;采用真有效值和线性补偿技术&#xff0c;将其隔离变换为标准的直流信号输出。DC24 伏安全电压供电&#xff0c;具有高精度、高隔离、高安全性、低功耗等特点&a…

用友NC Cloud importhttpscer接口任意文件上传漏洞

声明 本文仅用于技术交流&#xff0c;请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任。 一、漏洞描述 用友NC Cloud的importhttpscer接口如果存在任意文件上传…

WebStack 导航主题优化版

主题下载地址&#xff1a;WebStack 导航主题优化版.zip 修复记录&#xff1a; 1、修复已知BUG 2、修复手机版兼容问题 3、修复打开速度&#xff0c;原版打开速度太慢 4、优化页面代码&#xff0c;删除冗杂多余的CSS JS代码 环境要求 WordPress 4.4WordPress 伪静态PHP 5.…

LabVIEW专栏八、类

该章目的是可以开发仪器类。 一、类的概述 一般来说类有三大特性&#xff0c;封装&#xff0c;继承和多态。 在实际项目中&#xff0c;最主要是继承和多态&#xff0c;要搞清楚这两者的概念和在LabVIEW中是怎样应用的。在LabVIEW中&#xff0c;面向对象编程用到的就是LabVIE…

huggingface文件下载教程

文章目录 准备工作添加SSH Key生成Access Token 模型下载公开模型下载&#xff08;bert-base-chinese为例&#xff09;非公开模型下载&#xff08;Llama3为例&#xff09;权限申请官网预训练模型下载huggingface仓库下载 准备工作 添加SSH Key # 本地机器生成ssh key # step1…

欢乐钓鱼大师一键钓鱼,解放双手!

《钓鱼欢乐大师》是一款让玩家体验钓鱼乐趣的游戏&#xff0c;在游戏中&#xff0c;玩家可以通过技巧和策略钓到各种各样的鱼。为了提高钓鱼效率&#xff0c;让玩家更快地钓到大鱼&#xff0c;下面将介绍如何利用脚本来优化游戏体验。 第一步&#xff1a;准备工作 创建云机&…

目标检测综述

2D图像的目标检测是深度学习的热门领域&#xff0c; 在学术研究领域取得了巨大的进展&#xff0c;在工程中也被广泛应用。 按照stage划分&#xff0c; 主要可以分为one-stage 和two-stage 算法。 近年来&#xff0c; 随着transformer的流行&#xff0c; 基于transformer的检测…

基于springboot+vue的游艇停泊系统

一、系统架构 前端&#xff1a;vue2 | element-ui |html 后端&#xff1a;springboot | mybatis-plus 环境&#xff1a;jdk1.8 | mysql | maven | node 二、代码及数据库 三、功能介绍 01. web端-登录 02. web端-系统首页1 03. web端-系统首页2 04. web端-泊位 05. web…

YashanDB V23.2 LTS发版 | 共享集群首个长期支持版本

4月&#xff0c;YashanDB正式发布长期支持版本YashanDB V23.2 LTS&#xff0c;标志着YashanDB单机主备、共享集群和分布式实时数仓等完整产品体系&#xff0c;已全面进入可规模化使用的长期支持阶段&#xff1b;同时配套数据迁移工具、监控运维工具和开发者工具&#xff0c;可以…

串口服务器和光纤交换机的区别

串口服务器与光纤交换机在功能和应用上存在显著区别。串口服务器主要实现串口设备与以太网设备之间的数据转换与传输&#xff0c;适用于远程监控、数据采集等场景&#xff1b;而光纤交换机则专注于高速光纤网络中的数据交换&#xff0c;为大型企业或数据中心提供稳定、高效的数…