网络编程——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”这个词设置为屏蔽…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
