Wireshark抓包:理解TCP三次握手和四次挥手过程
TCP是一种面向连接、端到端可靠的协议,它被设计用于在互联网上传输数据和确保成功传递数据和消息。本节来介绍一下TCP中的三次握手和四次挥手。
文章目录
- 1 TCP头部格式
- 2 wireshark抓包分析
- 2.1 SEQ和ACK
- 2.2 三次握手
- 2.3 四次挥手
- 3 程序
1 TCP头部格式
TCP头部占据TCP段的前20个字节,其中包含端到端TCP套接字的参数和状态。如下图所示:
下面来逐个解释一下这些字段:
- 源端口(
Source port
):16位,用于标识源端口号(发送方的TCP端口) - 目标端口(
Destination port
):16位,用于标识目标端口号(接收方的TCP端口) - 序列号(
Sequence number
):32位,指示在TCP会话期间发送了多少数据。当建立新的TCP连接时,初始序列号是一个随机值。 - 确认号(``Acknowledgment Number`):32位,由接收方用于请求下一个TCP段。如果设置了ACK控制位,该字段包含段发送方期望接收的下一个序列号的值。一旦建立了连接,这个字段总是被发送。
- 数据偏移(
Data offset
):4位,显示头部中32位字的数量,也称为头部长度 - 保留数据(
Reserved data
):6位,保留字段,始终设置为零 - 控制位标志(
Control bit Flags
):TCP使用9位控制标志来管理特定情况下的数据流,例如建立连接、发送数据和终止连接URG
: 与后面的紧急指针字段相关,当设置了此位时,数据应被视为优先于其他数据。ACK
: 与ACK
相关,确认字段用于指示已成功接收到的数据量,如果设置了此字段,说明发送方期望接收方继续发送下一个TCP段PSH
: 推送功能,表示发送方希望接收方立即传输数据,而不必等到整个TCP段的数据都准备好再传输RST
: 重置连接,仅在存在无法恢复的错误时使用SYN
: 同步序列号,此标志用于设置初始序列号FIN
: 完成位用于结束TCP连接,因为TCP是全双工连接,所以双方都必须使用FIN位来结束连接
- 窗口(
Window
):16位,指定接收方愿意接收多少字节 - 校验和(
Checksum
):16位,用于对头部和数据进行错误检查 - 紧急指针(
Urgent Pointer
):如果设置了URG控制标志,该值表示与序列号的偏移,指示最后一个紧急数据字节 - 选项(
Options
):可选,长度可为0~320位之间的任意大小
2 wireshark抓包分析
程序流程:服务端监听本地环回地址127.0.0.1的12345端口,客户端则连接这个端口,连接上后服务端发送一个Hello, World!
给客户端。
先来了解一下SEQ
和ACK
的概念:
2.1 SEQ和ACK
客户端和服务器之间建立TCP连接时会进行三次握手。先来理解一下SEQ
、ACK
的概念:
- 序列号(
SEQ
): 表示发送方发送的数据的起始位置。每发送一个新的数据段,序列号就会递增。 - 确认号(
ACK
): 表示接收方期望下次收到的数据的序列号。当接收方收到数据后,它会发送一个带有确认号的ACK,告诉发送方它已成功接收到了特定序列号之前的所有数据。 - 下一个期望的ACK: 当接收方收到一段数据时,
ACK
表示已成功接收的数据的下一个期望的序列号。因此,下一个期望的ACK
号通常是上一个ACK
号加上接收到的数据的长度。
2.2 三次握手
1、客户端发送SYN
给服务端
- 在wireshark中
SEQ
使用相对0的值,为的是方便分析,所以这里是0
从上图中可以看到SYN
标识被设置:
2.服务端回复带有SEQ
和ACK
的SYN-ACK
数据包
如下图所示:
3.客户端向服务器发送一个带有ACK
号的数据包,确认服务器的序列号
如下图所示:
此时双方的SEQ
已同步,以上就是三次握手的内容。下面客户端和服务器可以独立地发送和接收数据。
4.服务器向客户端发送“Hello, World!”
5.客户端向服务器发送一个ACK号,确认服务器的消息
上一个ACK
号为1,长度为13,因此ACK
号将为13+1=14。
2.3 四次挥手
接着上面的抓包来看,在程序中,服务端发送完“Hello, World!”后就关闭了客户端的socket。
1.服务端发送FIN
给客户端
如下图所示:
2.客户端向服务器发送一个ACK号,确认服务器的FIN
请求
如下图所示:
3.TCP是一种全双工连接,因此,客户端也向服务器发送一条消息以关闭连接
- 前面的图中最后一行是红色的
RST
是我不小心直接关闭了程序,下面的图为重新抓的包,注意看最后两条即可
如下图所示:
4.服务器向客户端发送一个ACK号,确认客户端的FIN请求
如下图所示:
3 程序
本文的代码使用Windows环境下的网络编程库,所以需要在链接库中增加ws2_32
。
服务端
// Server.c#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>int main() {WSADATA wsaData;SOCKET listenSocket, clientSocket;struct sockaddr_in serverAddr, clientAddr;int addrLen = sizeof(clientAddr);char buffer[1024] = "Hello, World!";// Initialize Winsockif (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {fprintf(stderr, "WSAStartup failed\n");return 1;}// Create a socketif ((listenSocket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {fprintf(stderr, "Socket creation failed\n");WSACleanup();return 1;}// Set up server address informationmemset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");serverAddr.sin_port = htons(12345);// Bind the socketif (bind(listenSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {fprintf(stderr, "Bind failed\n");closesocket(listenSocket);WSACleanup();return 1;}// Listen for incoming connectionsif (listen(listenSocket, SOMAXCONN) == SOCKET_ERROR) {fprintf(stderr, "Listen failed\n");closesocket(listenSocket);WSACleanup();return 1;}printf("Server listening on 127.0.0.1:12345\n");// Accept a connection from a clientif ((clientSocket = accept(listenSocket, (struct sockaddr*)&clientAddr, &addrLen)) == INVALID_SOCKET) {fprintf(stderr, "Accept failed\n");closesocket(listenSocket);WSACleanup();return 1;}// Send data to the clientsend(clientSocket, buffer, strlen(buffer), 0);printf("Data sent to the client\n");// Clean upclosesocket(clientSocket);closesocket(listenSocket);WSACleanup();return 0;
}
客户端
// Client.c#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>int main() {WSADATA wsaData;SOCKET clientSocket;struct sockaddr_in serverAddr;char buffer[1024];// Initialize Winsockif (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {fprintf(stderr, "WSAStartup failed\n");return 1;}// Create a socketif ((clientSocket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {fprintf(stderr, "Socket creation failed\n");WSACleanup();return 1;}// Set up server address informationmemset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");serverAddr.sin_port = htons(12345);// Connect to the serverif (connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {fprintf(stderr, "Connection failed\n");closesocket(clientSocket);WSACleanup();return 1;}// Receive data from the serverint bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0);if (bytesRead > 0) {buffer[bytesRead] = '\0'; // Null-terminate the received dataprintf("Received data from server: %s\n", buffer);} else {fprintf(stderr, "Error receiving data\n");}while(1){if(recv(clientSocket, buffer, sizeof(buffer), 0) == 0){break;}}// Clean upclosesocket(clientSocket);WSACleanup();return 0;
}
相关文章:

Wireshark抓包:理解TCP三次握手和四次挥手过程
TCP是一种面向连接、端到端可靠的协议,它被设计用于在互联网上传输数据和确保成功传递数据和消息。本节来介绍一下TCP中的三次握手和四次挥手。 文章目录 1 TCP头部格式2 wireshark抓包分析2.1 SEQ和ACK2.2 三次握手2.3 四次挥手 3 程序 1 TCP头部格式 TCP头部占据…...

网络工程师-HCIA网课视频学习
这里是速成的,只积累下,自己未曾学习到的东西。通过书本补充知识点。 视频:hcia17-链路聚合_哔哩哔哩_bilibili hcia16-路由高级特性: hcia17-链路聚合: 由于如果根据视频来学习的话,感觉视频的总结并不…...

【每日刷题——语音信号篇】
思考与练习 练习2.1 语音信号在产生的过程中,以及被感知的过程中,分别要经过人体的哪些器官? 1.产生过程: 肺部空气 → \rightarrow →冲击声带 → \rightarrow →通过声道(可以调节) → \rightarrow →…...

Linux进程通信——IPC、管道、FIFO的引入
进程间的通信——IPC 进程间通信 (IPC,InterProcess Communication) 是指在不同进程之间传播或交换信息。 IPC的方式通常有管道 (包括无名管道和命名管道) 、消息队列、信号量、共享存储、Socket、Streams等。其中 Socket和Streams支持不同主机上的两个进程IPC。 …...
数理统计的基本概念(一)
文章目录 总体、样本与统计量总体及其分布样本及其分布统计量统计量概念样本矩顺序统计量及其分布样本中位数与样本极差经验分布函数 参考文献 总体、样本与统计量 总体及其分布 在数理统计中,称所研究的对象的全体为总体,总体中的元素称为个体。若总体…...

clickhouse分布式之弹性扩缩容的故事
现状 社区不支持喔,以后也不会有了。曾经尝试过,难道是是太难了,无法实现吗?因为他们企业版支持了,可能是利益相关吧,谁知道呢,毕竟开源也要赚钱,谁乐意一直付出没有回报呢。 社区…...

数据结构--串的基本概念
目录 串的基本概念 串的定义 串与线性表对比 串的基本操作 串的比较 字符集编码 乱码问题编辑 总结 串的存储结构 串的顺序存储编辑 串的链式存储 串的基本操作 1、求字串 2、比较 3、定位操作 总结 串的基本概念 串的定义 串与线性表对比 串的…...
音视频流媒体之 IJKPlayer FFmpeg Android 编译
FIJK dockerfile 编译环境 FROM --platformlinux/amd64 ubuntu:18.04RUN apt-get update && apt-get install -y \wget \unzip \git \gcc \g \make \python \yasm \pkg-config \protobuf-compiler \sudoRUN apt-get install -y openjdk-8-jdkENV ANDROID_HOME…...

记录一次较为完整的Jenkins发布流程
文章目录 1. Jenkins安装1.1 Jenkins Docker安装1.2 Jenkins apt-get install安装 2. 关联github/gitee服务与webhook2.1 配置ssh2.2 Jenkins关联2.3 WebHook 3. 前后端关联发布 1. Jenkins安装 1.1 Jenkins Docker安装 Docker很好,但是我没有玩明白如何使用Docke…...

Virtual安装centos后,xshell连接centos 测试及遇到的坑
首先来一张官方的图--各种网络模式对应的连接状况: 1. 网络使用Host-Only模式动态分配IP,点确定后,centos 上运行 system restart network ,使用ifconfig查看新的ip,XShell可以直接连上centos, 但是由于使用…...
【算法】最优乘车——bfs(stringsteam的实际应用,getline实际应用)
题目 H 城是一个旅游胜地,每年都有成千上万的人前来观光。 为方便游客,巴士公司在各个旅游景点及宾馆,饭店等地都设置了巴士站并开通了一些单程巴士线路。 每条单程巴士线路从某个巴士站出发,依次途经若干个巴士站,…...

『亚马逊云科技产品测评』活动征文|通过lightsail一键搭建Drupal VS 手动部署
『亚马逊云科技产品测评』活动征文|通过lightsail一键搭建Drupal 提示:授权声明:本篇文章授权活动官方亚马逊云科技文章转发、改写权,包括不限于在 Developer Centre, 知乎,自媒体平台,第三方开发者媒体等亚…...
使用 VuePress 和 Vercel 打造个人技术博客:实现自动化部署
什么是VuePress? 以下是VuePress官方文档的介绍:VuePress 是一个以 Markdown 为中心的静态网站生成器。你可以使用 Markdown 来书写内容(如文档、博客等),然后 VuePress 会帮助你生成一个静态网站来展示它们。VuePress 诞生的初…...

Re50:读论文 Large Language Models Struggle to Learn Long-Tail Knowledge
诸神缄默不语-个人CSDN博文目录 诸神缄默不语的论文阅读笔记和分类 论文名称:Large Language Models Struggle to Learn Long-Tail Knowledge ArXiv网址:https://arxiv.org/abs/2211.08411 官方GitHub项目(代码和实体)…...

Spring IOC - Bean的生命周期之依赖注入
在Spring启动流程中,创建的factoryBean是DefaultListableBeanFactory,其类图如下所示: 可以看到其直接父类是AbstractAutoireCapableBeanFactory,他主要负责完成Bean的自动装配和创建工作。 具体来说,AbstractAutowire…...

Android Termux安装MySQL,内网穿透实现公网远程访问
文章目录 前言1.安装MariaDB2.安装cpolar内网穿透工具3. 创建安全隧道映射mysql4. 公网远程连接5. 固定远程连接地址 前言 Android作为移动设备,尽管最初并非设计为服务器,但是随着技术的进步我们可以将Android配置为生产力工具,变成一个随身…...

OpenCV快速入门:像素操作和图像变换
文章目录 前言1. 像素操作1.1 像素统计1.2 两个图像之间的操作1.2.1 图像加法操作1.2.3 图像加权混合 1.3 二值化1.4 LUT(查找表)1.4.1 查找表原理1.4.2 代码演示 2 图像变换2.1 旋转操作2.1.1 旋转的基本原理2.1.2 代码实现 2.2 缩放操作2.3 平移操作2.…...

Django 路由配置(二)
一、路由 就是根据用户请求的URL链接来判断对应的出来程序,并返回处理结果,也是就是URL和django的视图建立映射关系. 二、Django请求页面的步骤 1、首先Django确定要使用的根URLconf模块,通过ROOT_URLCONF来设置,在settings.py配置…...

电子学会C/C++编程等级考试2022年06月(一级)真题解析
C/C++等级考试(1~8级)全部真题・点这里 第1题:倒序输出 依次输入4个整数a、b、c、d,将他们倒序输出,即依次输出d、c、b、a这4个数。 时间限制:1000 内存限制:65536输入 一行4个整数a、b、c、d,以空格分隔。 0 < a,b,c,d < 108输出 一行4个整数d、c、b、a,整数之…...

【C++】使用std::vector()函数实现矩阵的加、减、点乘、点除等运算
本文通过vector()函数表示矩阵的形式,对 加、减、点乘、点除等运算进行编码和运行,相应结果如下文所述。 #include <iostream> #include <vector>using namespace std;// 矩阵加法 vector<vector<int>> …...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...

人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...