首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

TCP三次握手和四次挥手

编程知识
2024年08月14日 16:30

TCP三次握手和四次挥手详解

在网络通信中,TCP(传输控制协议)是一个非常重要的协议,用于确保数据在不可靠的网络环境中能够可靠传输。TCP通过三次握手(Three-way Handshake)建立连接,通过四次挥手(Four-way Termination)终止连接。


一、TCP三次握手

TCP的三次握手用于确保客户端和服务器之间的连接是可靠的,并且双方都准备好进行数据传输。三次握手的过程如下:

  1. 第一次握手:客户端发送SYN

    • 客户端向服务器发送一个SYN(同步序列编号)报文,表示客户端希望与服务器建立连接。此时,客户端进入SYN-SENT状态。
    • 报文中包含一个初始序列号(ISN),用于后续数据传输中的序列控制。
  2. 第二次握手:服务器发送SYN-ACK

    • 服务器接收到SYN报文后,向客户端发送一个SYN-ACK(同步确认)报文,表示同意建立连接。此时,服务器进入SYN-RECEIVED状态。
    • SYN-ACK报文包含服务器自己的ISN和客户端的ISN+1,表明服务器已收到客户端的SYN,并将自己的SYN发送给客户端。
  3. 第三次握手:客户端发送ACK

    • 客户端接收到SYN-ACK报文后,向服务器发送一个ACK(确认)报文,确认服务器的SYN已经收到。此时,客户端进入ESTABLISHED状态,连接建立成功。
    • 服务器接收到ACK报文后,也进入ESTABLISHED状态,表示连接已准备好进行数据传输。

通过三次握手,双方确认了彼此的发送和接收能力,连接正式建立。

 

这个过程类似于打电话的三个过程:

1.拨号。拨号相当于第一次握手。

2.接通。对方接通后为第二次握手。

3.回应。我方听到声音并回应为第三次握手。


二、TCP四次挥手

TCP的四次挥手用于终止客户端和服务器之间的连接,确保双方都能够优雅地关闭连接。四次挥手的过程如下:

  1. 第一次挥手:客户端发送FIN

    • 客户端发送一个FIN(终止)报文,表示客户端已经没有数据要发送了,要求关闭连接。此时,客户端进入FIN-WAIT-1状态。
    • FIN报文可能包含最后一段数据,或者仅仅表示终止发送。
  2. 第二次挥手:服务器发送ACK

    • 服务器接收到FIN报文后,向客户端发送一个ACK报文,确认客户端的FIN已经收到。此时,服务器进入CLOSE-WAIT状态,客户端进入FIN-WAIT-2状态。
    • 此时,服务器可能仍有未发送的数据,因此不会立即关闭连接。
  3. 第三次挥手:服务器发送FIN

    • 服务器发送完所有剩余的数据后,向客户端发送一个FIN报文,表示服务器也准备关闭连接。此时,服务器进入LAST-ACK状态。
    • 客户端接收到FIN报文后,发送最后一个ACK报文,确认收到服务器的FIN。此时,客户端进入TIME-WAIT状态。
  4. 第四次挥手:客户端发送ACK

    • 客户端发送的最后一个ACK报文确认了服务器的FIN报文后,客户端进入TIME-WAIT状态,等待一段时间(通常为2倍的最大报文段寿命),确保服务器收到ACK。
    • 如果在TIME-WAIT状态期间没有收到任何重传的FIN报文,客户端将进入CLOSED状态,表示连接已经完全关闭。

通过四次挥手,TCP连接得以优雅地关闭,确保所有的数据都得到了完整的传输和确认。

 

 

示例:

import socket
import time

# 服务端代码
def server():
    # 创建TCP套接字
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 绑定IP地址和端口号
    server_socket.bind(('localhost', 12345))
    # 监听连接请求
    server_socket.listen(1)
    print("Server is listening...")

    # 接受客户端连接
    conn, addr = server_socket.accept()
    print(f"Connected by {addr}")

    # 模拟服务器发送数据
    conn.sendall(b'Hello, Client!')

    # 接收客户端消息
    data = conn.recv(1024)
    print(f"Received: {data.decode()}")

    # 关闭连接
    conn.close()
    server_socket.close()
    print("Server connection closed.")

# 客户端代码
def client():
    # 创建TCP套接字
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 连接服务器
    client_socket.connect(('localhost', 12345))
    print("Client connected to server.")

    # 接收服务器消息
    data = client_socket.recv(1024)
    print(f"Received: {data.decode()}")

    # 模拟客户端发送数据
    client_socket.sendall(b'Thank you, Server!')

    # 关闭连接
    client_socket.close()
    print("Client connection closed.")

# 模拟TCP三次握手和四次挥手
if __name__ == "__main__":
    # 启动服务端
    import threading
    server_thread = threading.Thread(target=server)
    server_thread.start()

    # 延迟启动客户端以确保服务端已启动
    time.sleep(1)

    # 启动客户端
    client()

    # 等待服务端线程结束
    server_thread.join()

 

  • 服务端部分:

    • 使用 socket.socket() 创建一个TCP套接字,并绑定到 localhost 上的端口 12345
    • 通过 listen() 方法让服务器开始监听客户端连接。
    • 使用 accept() 接受客户端的连接请求,并返回一个新的套接字 conn,用于与客户端进行通信。
    • 服务器发送一条消息给客户端,并接收客户端的响应后,关闭连接。
  • 客户端部分:

    • 同样使用 socket.socket() 创建一个TCP套接字。
    • 通过 connect() 方法连接到服务器的IP和端口。
    • 客户端接收到服务器的消息后,发送一个响应消息,并关闭连接。
  • 主程序部分:

    • 使用Python的 threading 模块来同时运行服务器和客户端,模拟TCP的三次握手和四次挥手过程。

输出:

Server is listening...
Client connected to server.
Connected by ('127.0.0.1', random_port)
Received: Hello, Client!
Received: Thank you, Server!
Client connection closed.
Server connection closed.

 

From:https://www.cnblogs.com/zx618/p/18359423
本文地址: http://shuzixingkong.net/article/1101
0评论
提交 加载更多评论
其他文章 JVM 参数配置
JVM 参数设置入门案例 JVM 的内存参数众多,但是在实际应用中主要关注堆内存的大小设置及堆内存中新生代和老年代的大小设置,下面看一个简单的 JVM 启动参数设置案例: java -server -Xms3g -Xmx3g -XX:NewSize=1g -XX:MetaspaceSize=128m
使用Django-Channels实现websocket通信+大模型对话
前言 最近一直在做这个大模型项目,我选了 Django 作为框架(现在很多大模型应用都用的 FastAPI,不过我已经用习惯 Django 了) 之前使用 AspNetCore 作为后端的时候,我先后尝试了 Blazor Server,WebAPI SSE(Server Sent Event)等方案
使用Django-Channels实现websocket通信+大模型对话 使用Django-Channels实现websocket通信+大模型对话
什么是依赖倒置原则
依赖倒置原则(Dependency Inversion Principle, DIP)是面向对象设计原则之一,它是SOLID原则中的"D"。依赖倒置原则的核心思想是高层策略性业务规则不应该依赖于低层的具体实现细节,而两者都应该依赖于抽象。 依赖倒置原则主要包含两个基本点: 抽象不
kubernetes负载感知调度
背景 kubernetes 的原生调度器只能通过资源请求来调度 pod,这很容易造成一系列负载不均的问题, 并且很多情况下业务方都是超额申请资源,因此在原生调度器时代我们针对业务的特性以及评估等级来设置 Requests/Limit 比例来提升资源利用效率。 在这种场景下依然存在很多问题: 节点负载
kubernetes负载感知调度 kubernetes负载感知调度
Java 大文件IO操作效率对比【我说说 你瞅瞅】
Java 文件IO操作效率对比 通过以下几种方式读取数据文件,并连续进行 10 次测试: 1. FileInputStream + byte[] 文件字节输入流 + 字节数组读取方式 2. FileInputStream + Scanner 文件字节输入流 + Scanner 读取方式 3. Fi
这次轮到AntV增强Awesome-Graphs
AntV团队迅速将G6图可视化引擎融入Awesome-Graphs项目,发布1.2.0版本,提升交互体验,包括路径高亮、模糊搜索等功能,现邀请体验并征集改进意见。
这次轮到AntV增强Awesome-Graphs 这次轮到AntV增强Awesome-Graphs 这次轮到AntV增强Awesome-Graphs
SenseCraft 部署模型到Grove Vision AI V2图像处理模块
今天教大家快速上手Grove Vision AI V2 图像处理模块,我们将一起探讨如何利用 SenseCraft 部署 AI 模型,和如何通过XIAO ESP32C3调用这些模型,轻松实现智能视觉功能!
SenseCraft 部署模型到Grove Vision AI V2图像处理模块 SenseCraft 部署模型到Grove Vision AI V2图像处理模块 SenseCraft 部署模型到Grove Vision AI V2图像处理模块
PowerShell快速修改多个文件的名称
本文介绍基于PowerShell语言,对文件夹中全部文件的名称加以批量替换、修改的方法。 在之前的文章中,我们介绍了基于Python语言,批量修改大量文件的名称的方法。当时我们修改文件名的需求比较复杂,因此选择了用Python语言来实现;而在我们的需求重命名规则相对比较简单时,则可以基于PowerS
PowerShell快速修改多个文件的名称 PowerShell快速修改多个文件的名称 PowerShell快速修改多个文件的名称