网络编程——wireshark抓包、tcp粘包
目录
一、前言
1.1 什么是粘包
1.2 为什么UDP不会粘包
二、编写程序
文件树
客户端程序
服务器程序
tcp程序
头文件
makefile
三、 实验现象
四、改进实验
五、小作业
一、前言
最近在做网络芯片的驱动,验证功能的时候需要借助wireshark这个工具,今天就来回顾下网络编程相关的知识。
1.1 什么是粘包
在网络通信过程中,数据包往往是连续发送的,尤其是在稳定且高速的网络连接中。这种连续传输可以提高数据传输的效率,减少因等待发送或接收数据包而产生的延迟。
在TCP/IP协议中,由于TCP是一个面向连接的、可靠的、基于字节流的传输层通信协议,它不保留消息边界。这意味着在发送端连续发送的多个数据包,在接收端可能会被合并成一个大的数据包接收(粘包),或者一个完整的数据包被拆分成多个小数据包接收(拆包)。
|eth header|IP header|tcp header| data |
[12 bytes] | 20 bytes| 20 bytes |"abc" |
|
data只占4个字节,
而为了发送这4个字节,需要12+20+20,至少52个字节,会造成极大的资源浪费
1.2 为什么UDP不会粘包
- 独立的传输机制:由于UDP数据报的独立性,每个数据报都是单独发送和接收的,不会与其他数据报混合在一起。因此,在接收端,每个UDP数据报都可以被清晰地识别和处理,不会出现TCP中可能遇到的粘包问题。
- 没有面向连接的数据流:UDP不像TCP那样提供面向连接的数据流服务。TCP为了保证数据的可靠传输,会对数据进行拆分、重排和合并等操作,这些操作可能会导致粘包现象。而UDP则没有这些操作,它直接发送和接收完整的数据报,因此不会出现粘包问题。
- 基于数据报的传输模式:UDP的传输模式是基于数据报的,即每个数据报都是一个完整的单元,具有独立的传输路径和生命周期。这种传输模式使得UDP能够避免TCP中可能出现的粘包和拆包问题。
了解了以上概念我们开始验证这个问题。
二、编写程序
文件树
这是我们的目录结构分为服务器和客户端

客户端程序
#include "tcp.h"int main(int argc, char *argv[])
{int fd;int ret, i = 2;char buf[BUFSIZ] = {"===test===\n"};/*检查参数*/Argment(argc, argv);fd = SocketInit(argv, false);/*发送数据*/while(i--){do {ret = send(fd, buf, strlen(buf), 0);}while(ret < 0 && errno == EINTR); //如果信号导致的错误,继续执行if(ret < 0)ErrExit("recv");else if(!ret)break;printf("send data:%s", buf);fflush(stdout);}close(fd);return 0;
}
我们进行两次连发看看效果是什么样的
服务器程序
#include "tcp.h"int main(int argc, char *argv[])
{int fd, newfd;int ret;char buf[BUFSIZ];Addr_in client_addr;socklen_t addrlen = sizeof(Addr_in);/*检查参数*/Argment(argc, argv);/*创建服务端套接字*/fd = SocketInit(argv, true);/*接收客户端连接*/do {newfd = accept(fd, (Addr *)&client_addr, &addrlen);}while(newfd < 0 && errno == EINTR); //如果信号导致的错误,继续执行if(newfd < 0)ErrExit("accept");/*接收客户端数据*/while(1){do {ret = recv(newfd, buf, BUFSIZ, 0);}while(ret < 0 && errno == EINTR); //如果信号导致的错误,继续执行if(ret < 0)ErrExit("recv");else if(!ret)break;elseprintf("[%s:%d]buf:%s\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), buf);printf("getchar()\n");getchar();}close(newfd);close(fd);return 0;
}
tcp程序
#include "tcp.h"void Argment(int argc, char *argv[]){if(argc < 3){fprintf(stderr, "%s <addr><port>\n", argv[0]);exit(EXIT_FAILURE);}
}int SocketInit(char *argv[], bool server){int fd;Addr_in addr;func_t func = server?bind:connect;/*创建套接字*/if( (fd = socket(AF_INET, SOCK_STREAM, 0) ) < 0)ErrExit("socket");/*设置通信结构体*/bzero(&addr, sizeof(addr) );addr.sin_family = AF_INET;addr.sin_port = htons( atoi(argv[2]) );if (inet_aton(argv[1], &addr.sin_addr) == 0) {fprintf(stderr, "Invalid address\n");exit(EXIT_FAILURE);}/*地址快速重用*/int b_reuse = 1;setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &b_reuse, sizeof(int) );/*发起连接请求或绑定地址*/if( func(fd, (Addr *)&addr, sizeof(addr) ) )ErrExit("connect or bind");if(server){/*监听模式*/if( listen(fd, BACKLOG) )ErrExit("listen");}return fd;
}
头文件
#ifndef _TCP_H_
#define _TCP_H_#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdbool.h>
#include <string.h>#define BACKLOG 5#define ErrExit(msg) do { perror(msg); \exit(EXIT_FAILURE); } while(0)typedef struct sockaddr Addr;
typedef struct sockaddr_in Addr_in;typedef int (* func_t)(int, const Addr *, socklen_t);void Argment(int argc, char *argv[]);
int SocketInit(char *argv[], bool server);
#endif
makefile
all:server client
CC=gcc
CFLAGS=-g -Wallserver:tcp.c server.cclient:tcp.c client.cclean:rm server client
三、 实验现象


在ubuntu22.04和ubuntu18.04上都能实现。

但是发现有个问题

还有发两次的现象

四、改进实验
先ping下百度,看看百度的ip是多少
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <unistd.h>int main(int argc, const char *argv[])
{int fd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in sin = {.sin_family = AF_INET,.sin_port = htons(80),};if (inet_aton("110.242.68.66", &sin.sin_addr) == 0) {fprintf(stderr, "Invalid address\n");exit(EXIT_FAILURE);}if(connect(fd, (struct sockaddr *)&sin, sizeof(sin) ) < 0) {perror("connect");exit(0);}send(fd, "hello", 5, 0);send(fd, "hello", 5, 0);send(fd, "hello", 5, 0);send(fd, "hello", 5, 0);send(fd, "hello", 5, 0);send(fd, "hello", 5, 0);close(fd);return 0;
}
写完程序后运行wireshark

选择上互联网用的网卡
我们会发现6个hello被划分到了两个包里一个1个hello另一个5个,但是我们用了6次send正常应该6个包的,这就是粘包现象。


注意:PSH代表有数据包,FIN代表没有数据包了
五、小作业
兄弟们可以试试分包现象的验证,搞一个大的包看看是不是会被分开。
相关文章:
网络编程——wireshark抓包、tcp粘包
目录 一、前言 1.1 什么是粘包 1.2 为什么UDP不会粘包 二、编写程序 文件树 客户端程序 服务器程序 tcp程序 头文件 makefile 三、 实验现象 四、改进实验 五、小作业 一、前言 最近在做网络芯片的驱动,验证功能的时候需要借助wireshark这个工具&…...
el-table合计行更新问题
说明:在使用el-table自带的底部合计功能时,初始界面不会显示合计内容 解决方案:使用 doLayout()方法 updated() {this.$nextTick(() > {this.$refs[inventorySumTable].doLayout();});},完整代码: // show-summary:…...
ChatGPT:数据库不符合第二范式示例
ChatGPT:数据库不符合第二范式示例 这张图片为什么不符合数据库第二范式 这个表格不符合数据库第二范式(2NF)的原因如下: 1. 数据库第二范式(2NF)定义 第二范式要求一个数据库表格在满足第一范式…...
27、美国国家冰雪中心(NSIDC)海冰密集度月数据下载与处理
文章目录 一、前言二、数据下载三、使用Ponply查看数据结构四、代码一、前言 处理美国国家冰雪中心(NSIDC)的海冰密集度月度数据时,坐标转换是一个重要的步骤。NSIDC提供的数据通常采用极地球面坐标系,需要将其转换为常用的地理坐标系(如经纬度)以便进行分析和可视化。 坐…...
vite环境下使用bootstrap
环境 nodejs 18 pnpm 初始化 pnpm init pnpm add -D vite --registry http://registry.npm.taobao.org pnpm add bootstrap popperjs/core --registry http://registry.npm.taobao.org pnpm add -D sass --registry http://registry.npm.taobao.org新建vite.config.js cons…...
Laravel视图渲染封装
第一种 app/Helpers/ViewHelper.php 创建一个辅助函数,用于动态确定视图路径: <?php if (!function_exists(fetchView)) {function fetchView($data []){$currentAction \Route::currentRouteAction();list($controller, $method) explode(, $c…...
C++学习补充2:MySQL select 查询
MySQL select 查询 MySQL 查询 select时, 不区分大小写的。 MySQL 在默认情况下是区分大小写的,但是它的行为可能因配置和使用的字符集而有所不同。以下是一些可能导致查询在 SELECT 语句中不区分大小写的原因: 字符集设置:如果…...
uni-app声生命周期
应用的生命周期函数在App.vue页面 onLaunch:当uni-app初始化完成时触发(全局触发一次) onShow:当uni-app启动,或从后台进入前台时显示 onHide:当uni-app从前台进入后台 onError:当uni-app报错时触发,异常信息为err 页面的生命周期 onLoad…...
排序算法--堆排序
基本思想 堆排序的基本思想是,将待排序的元素构建成一个最大堆或最小堆。对于最大堆来说,堆顶是整个堆中的最大元素;对于最小堆来说,堆顶是整个堆中的最小元素。然后,将堆顶元素与堆中最后一个元素交换,并…...
iPhone 在 App Store 中推出的 PC 模拟器 UTM SE
PC 模拟器是什么?PC 模拟器是一种软件工具,它模拟不同硬件或操作系统环境,使得用户可以在一台 PC 上运行其他平台的应用程序或操作系统。通过 PC 模拟器,用户可以在 Windows 电脑上体验 Android 应用、在 Mac 电脑上运行 Windows …...
FastAPI删除mongodb重复数据(数据清洗)
在 FastAPI 中删除 MongoDB 重复数据,你需要结合使用 MongoDB 查询和 FastAPI 的路由功能。以下是一个通用的例子,演示如何删除特定字段上的重复数据: 1. 定义数据模型: from pydantic import BaseModel, Field from bson import ObjectId …...
移动UI:排行榜单页面如何设计,从这五点入手,附示例。
移动UI的排行榜单页面设计需要考虑以下几个方面: 1. 页面布局: 排行榜单页面的布局应该清晰明了,可以采用列表的形式展示排行榜内容,同时考虑到移动设备的屏幕大小,应该设计合理的滚动和分页机制,确保用户…...
如何解决 uni-app 项目中 “文件查找失败:‘crypto-js‘“ 的问题
在开发使用 uni-app 框架的项目时,遇到依赖问题是常见的。本文将介绍如何解决编译过程中出现的 “文件查找失败:‘crypto-js’” 错误,并说明这种错误为什么会发生以及如何避免。 问题背景 在对 uni-app 项目进行编译时,我们可能…...
Apache DolphinScheduler 3.2.2 版本正式发布!
Apache DolphinScheduler 3.2.2 版本正式发布! 近日,Apache DolphinScheduler 发布了 3.2.2 版本。此版本主要基于 3.2.1 版本进行了 bug 修复,新增若干特性,并进行了众多改进和 Bug 修复,以及文档修复等。 …...
汇川CodeSysPLC教程03-2-6 ModBus TCP
什么是ModBus TCP? ModBus TCP是一种基于TCP/IP协议的工业网络通信协议,常用于工业自动化和控制系统。它是ModBus协议的一个变种,ModBus协议最初由Modicon(现在是施耐德电气的一部分)在1979年开发。 以下是ModBus TC…...
【Python机器学习】决策树的构造——划分数据集
分类算法除了需要测量信息熵,还需要划分数据集,度量划分数据集的熵,以便判断当前是否正确划分了数据集。 我们将对每个特征划分数据集的结果计算一次信息熵,然后判断按照哪个特征划分数据集是最好的划分方式。 想象一个分部在二…...
Pip换源使用帮助
PyPI 镜像使用帮助 PyPI 镜像帮助提高包安装的速度,特别是当默认源访问较慢时。镜像每次同步成功后,每隔 5 分钟进行更新,确保镜像内容尽量与官方源保持一致。 pip 临时使用 如果您只想在一次安装中使用镜像,可以使用以下命令&…...
力扣1089复写0
1089. 复写零 - 力扣(LeetCode) 我们的思路是利用类似双指针的方式去解答,来看下代码 class Solution { public:void duplicateZeros(vector<int>& arr){int cur 0, dest -1, n arr.size();while (cur < n){if (arr[cur])d…...
10 VUE Element
文章目录 VUE1、概述2、快速入门3、Vue 指令4、生命周期5、案例 Elemant1、快速入门2、Element 布局3、常用组件-案例 VUE 1、概述 Vue 是一套前端框架,免除原生JavaScript中的DOM操作,简化书写基于MVVM(Model-View-ViewModel)思想,实现数据…...
独立游戏《星尘异变》UE5 C++程序开发日志8——实现敏感词过滤功能(AC自动机)
在游戏中经常会有需要玩家输入一些内容的功能,例如聊天,命名等,这款游戏只有在存档时辉用到命名功能,所以这个过滤也只是一个实验性的功能,我们将使用AC自动机来实现,这是在我们把“csdn”这个词设置为屏蔽…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...
Mysql故障排插与环境优化
前置知识点 最上层是一些客户端和连接服务,包含本 sock 通信和大多数jiyukehuduan/服务端工具实现的TCP/IP通信。主要完成一些简介处理、授权认证、及相关的安全方案等。在该层上引入了线程池的概念,为通过安全认证接入的客户端提供线程。同样在该层上可…...
Axure零基础跟我学:展开与收回
亲爱的小伙伴,如有帮助请订阅专栏!跟着老师每课一练,系统学习Axure交互设计课程! Axure产品经理精品视频课https://edu.csdn.net/course/detail/40420 课程主题:Axure菜单展开与收回 课程视频:...
Springboot 高校报修与互助平台小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,高校报修与互助平台小程序被用户普遍使用,为…...
