粘包问题

article/2025/10/13 16:50:00

TCP是一个面向连接的,可靠的,安全的流式协议

什么是粘包

粘包是指的是数据和数据之间没有没有明确的分界线,导致不能够正确的传输数据(只有TCP会粘包 UDP 永远不会粘包),粘包问题只针对于一切字节流的协议

TCP也可以称为流式协议,UDP称为数据报式协议

对于流式协议:发送端可以1K1K的发送数据,接收端可以2k2k的提取数据,也可以3K4K的提取数据,所以对于接收端应用程序中看到的数据就是一个整体,“数据流”,一条消息里面有多少字节应用程序是看不见的,所以TCP协议面向字节流,就会出现粘包问题,而UDP这种面向消息的协议,每个UDP段都是一条消息,接收方必须以消息为单位进行提取数据,不能一次提取任意字节的数据

所谓的粘包问题就是接收方不知道消息和消息之间的边界,不知道一次提取多少个字节导致的

粘包问题出现的具体原因

应用程序无法直接操作硬件,应用程序想要操作数据必须要将数据交给操作系统,OS会为应用提供数据传输的服务,所以OS不会立刻把数据发出去,会为应用程序提供一个缓冲区,存在临时的数据,
发送方:

	当应用程序调用send函数时候,应用程序会将数据从应用程序拷贝到操作系统缓存里面,再由OS从缓冲区里面读数据,把数据发出去

接收方:

	对方计算机收到的数据也是OS先收到的,至于应用程序如何处理这些数据,OS不知道,所以同样需要将数据先存储到OS 的缓冲区里面,当应用程序调用recv的时候,实际上是将OS缓冲区里面的数据拷贝到应用程序的过程

粘包问题的解决

服务端如果想要保证每次都能接收到客户端发来的不定长度的数据包,程序员应该如何来解决这个问题呢?

  1. 使用应用层协议(http,https)来封装要传输的不定长的数据包
  2. 再每个数据的后面添加一些特殊字符,如果遇到特殊字符,说明这条数据接收完毕了
  • 每接收一个字符就要对这些字符进行判定,判定是不是特殊的字符串,效率很低
  1. 在发送数据快之前,在数据块之前添加一个固定大小的包头:数据头+数据块
  • 数据头:存储当前数据包的总字节数,接收端先接收数据头,然后再根据数据头接收对应的大小
  • 数据块:当前数据包的内容

解决方案

如果使用TCP进行套接字通信,如果发送的数据包连在了一块,导致接收端无法解析,我们通常使用添加包头的方式来轻松解决这个问题,包头的大小为4个字节(一个int类型),存储当前数据块的总字节数
在这里插入图片描述

发送端

  1. 根据发送的数据长度N****动态申请一个固定大小的内存:N+4(4是包头占用的字节数)
  2. 将待发送的数据的总长度写入申请的内存的前4个字节(memcpy前4个字节),此处应该先将其转化为网络字节序(大端),再写入
  3. 将待发送的数据拷贝到包头后面的地址空间中,将完整的数据包发送出去(字符串没有字节序问题)
  4. 用一个函数来进行发送,把所有的字节全部发送出去
  5. 释放申请的堆内存空间

//发送指定长度的字符串
int writen(int fd,const char* msg,int size)//发送,避免粘包,丢包
{const char * buf=msg;//buf指向的是msg的首地址int count=size;//剩余的长度没有被发送出去的字节数while(count>0){//不停的进行数据发送int len=send(fd,buf,count,0);//send成功返回发送出去的字节数,否则失败返回-1,fd为向哪一个文件描述符里面发送//buf是发送的数据//count是数据的长度if(len==-1){//发送失败return -1;}else if(len==0){//一个字节都没有发送出去continue;//再发送一次}else{buf+=len;//buf这个指针往后移动,后面buf就全部发送了出去count-=len;//count为剩余的字节数,变成0的话就发送完成了}}return size;//发送成功}//这个加包头的操作就是这样了,其他客户端该怎么发还是怎么发送
//发送数据
//len为数据的大小 
//msg为发送的数据 
int sendmsg(int cfd,const char* msg,int len)
{if(cfd<0||msg==nullptr||len<=0){exit(1);}char * data=(char*)malloc(sizeof(len+4));//先动态申请一些内存,+4是为了存数据头int biglen=htonl(len);//把要发送的数据的长度先转化成网络字节序memcpy(data,&biglen,4);//把biglen的浅4个字节拷贝到data里面//把我们需要的数据也拷贝到这一个内存里面去memcpy(data+4,msg,len);//数据拷贝完之后就要发送数据了int ret=writen(cfd,data,len+4);//+4是因为要加上这个数据的包头,把data传过去发送,连通它的头if(ret==-1){close(cfd);//函数调用失败,把文件描述符关掉}//发送完之后再把内存给释放掉free(data);
}

接收端

  1. 首先先接收4个字节(包头,记录了接收的数据的长度),并将它从网络字节序转化为主机字节序,这样就可以获得这些数据的总长度了
  2. 根据得到的数据块长度申请固定大小的堆内存,用于存储待接收的信息
  3. 处理接收的数据
  4. 释放存储数据的堆内存
//接收端
//接收指定字节个数int readn(int fd,char* buf,int size)//buf里面就是我们要把数据读取到的地方
{//我们需要往buf这个内存地址里面写数据了,所以不能加const//我们需要记录还需要读取多少个字节,以及读取到的位置char* pt=buf;int count=size;//我们剩余要接收的字节数while(count>0){int len=recv(fd,pt,count,0);//pt我们需要读取的地址,count就是我们需要读取的字节数,len就是实际读取到的长度if(len==-1){//读取失败return -1;}else if(len==0){//发送端已经断开了连接return size-count;//我们就返回收到的字节数}else{//正常的读取了pt+=len;count-=len;}}return size;//成功返回
}//接收函数
int recvmsg(int fd,char** msg)//这里的msg是一个输出型参数
{//我们需要先把数据头给读出来,看它的数据是有多少的数据int len=0;readn(fd,(char*)&len,4);//我们把数据读取到len里面//现在还是网络字节序,我们需要将它转化为主机字节序len=ntohl(len);cout<<"要接收到的数据块的长度为"<<len<<endl;//根据我们读取到的长度len(有效数据的大小)来分配长度char* data=(char*)malloc(sizeof(len+1));//+1是‘\0’,字符串结束的标志//再去调用这个函数int length=readn(fd,data,len);//我们要接收的数据长度是lenif(length==len){cout<<"读取成功"<<endl;}else{//接收数据失败了cout<<"接收数据失败了"<<endl;close(fd);free(data);//因为接收失败了,所以这块内存就没有意义了return -1;}data[len]='\0';*msg=data;return length;
}

http://chatgpt.dhexx.cn/article/iWPs4Aog.shtml

相关文章

粘包现象与解决粘包问题

粘包现象与解决粘包问题 一、引入 粘包问题主要出现在用TCP协议传输中才会出现的问题,UDP不会出现,因为TCP传输中他会服务端会一次性把所有东西一并丢入缓存区,而读取的内容大小有时候没法准确的做到一一读取,所有会存在粘包。 而UDP他传输的时候是吧一个个内容丢过去,不管客…

粘包

粘包 一、什么是粘包二、为什么会粘包三、粘包解决思路 一、什么是粘包 粘包是指发送方发送的若干数据到接收方&#xff0c;而接收方在接收数据时这些数据粘在一起&#xff0c;后一包数据头紧接着前一包数据尾部。 二、为什么会粘包 首先了解一下socket收发消息原理&#xff1…

网络通讯中粘包的处理

参考&#xff1a;网络通讯中粘包的处理 - 走看看 在网络通讯中&#xff0c;不仅仅是TCP通讯&#xff0c;也包括串口通讯中&#xff0c;我们经常会遇到数据包粘连的问题&#xff0c;本文详细介绍粘包问题产生的原因和解决办法。 一、粘包定义 TCP 传输中&#xff0c;客户端发送…

什么是粘包?

TCP/IP 协议簇建立了互联网中通信协议的概念模型&#xff0c;该协议簇中的两个主要协议就是 TCP 和 IP 协议。TCP/ IP 协议簇中的 TCP 协议能够保证数据段&#xff08;Segment&#xff09;的可靠性和顺序&#xff0c;有了可靠的传输层协议之后&#xff0c;应用层协议就可以直接…

【HUST】信息系统安全:Ret2libc多函数调用,ASLR两种情况(2)

注&#xff1a;感谢这位大佬的帮忙&#xff0c;没有他我估计还在github里面或者其他博客里面瞎找小雨aaa Ret2libc:Return to libc,顾名思义&#xff0c;就是通过劫持控制流使控制流指向libc中的系统函数&#xff0c;从而实现打开shell等其他工作。 在本次作业中&#xff0c;…

Linux ALSA音频工具

参考&#xff1a; ALSA 音频工具 amixer、aplay、arecord Linux Alsa ALSA的配置文件 音频录制——arecord 音频播放——aplay 音频配置——amixer alsamixer与amixer的区别 alsamixer是Linux音频框架ALSA工具之一&#xff0c;用于配置音频各个参数; alsamixer是基于文本图形…

[pwn]ROP:绕过ASLRNX

[详细] ROP&#xff1a;绕过ASLR&NX 这次使用的程序是Defcon - 2015初赛题目&#xff0c;r0pbaby&#xff0c;也是一道经典的pwn题目了。 程序链接&#xff1a;https://pan.baidu.com/s/1kr6z_crZfW7qNjtASmRMGw 提取码&#xff1a;eajs NX策略是指在栈中的代码不会被执行…

ORA-445报错与ASLR

数据库多次出现ORA-00445: background process "J002" did not start after 30 seconds报错及ORA-3136错误 查看相关文档(文档 ID 1600807.1)&#xff0c;两个报错都可能与内存压力过大有关 另外关于ORA-00445还有另一篇文档提到&#xff0c;在Oracle启用ASLR会无法…

[二进制学习笔记]Ubuntu20.04关闭开启ASLR

文章目录 Ubuntu20.04关闭开启ASLR Ubuntu20.04关闭开启ASLR ​ ASLR(Address space layout randomization)是一种针对缓冲区溢出的安全保护技术&#xff0c;通过对堆、栈、共享库映射等线性区布局的随机化&#xff0c;通过增加攻击者预测目的地址的难度&#xff0c;防止攻击者…

ASLR和PIE的区别

总结&#xff1a;ASLR 不负责代码段以及数据段的随机化工作&#xff0c;这项工作由 PIE 负责。但是只有在开启 ASLR 之后&#xff0c;PIE 才会生效。

【HUST】信息系统安全:Ret2libc多函数调用,ASLR两种情况(1)

Ret2libc:Return to libc,顾名思义&#xff0c;就是通过劫持控制流使控制流指向libc中的系统函数&#xff0c;从而实现打开shell等其他工作。 在本次作业中&#xff0c;我们的目标是通过运行stack.c程序来访问系统上的/tmp/flag程序的内容&#xff0c;其中&#xff0c;可以看到…

Linux ALSA声卡驱动之五:移动设备中的ALSA(ASoC)

1. ASoC的由来 ASoC--ALSA System on Chip &#xff0c;是建立在标准ALSA驱动层上&#xff0c;为了更好地支持嵌入式处理器和移动设备中的音频Codec的一套软件体系。在ASoc出现之前&#xff0c;内核对于SoC中的音频已经有部分的支持&#xff0c;不过会有一些局限性&#xff1a…

astrill android,Astrill

你想知道你所用的网络速度是多少吗&#xff1f;你想在全球任何地方都可以使用到手机网络吗&#xff1f;你想在需要下载文件时定位到信号最强的地方进行传输吗&#xff1f;小编今天为企业家和用户安利一款手机测速游戏——Astrill APP&#xff01;用户可以随时随地的查询到自己的…

Linux下 ASLR功能与 -no-pie 选项说明

一. Linux下ASLR功能 1. ASLR 技术介绍 ASLR 技术是一种针对缓冲区溢出的安全保护技术。 ASLR&#xff0c;全称为 Address Space Layout Randomzation&#xff0c;地址空间布局随机化。ASLR 技术在 2005 年的 kernel 2.6.12 中被引入到 Linux 系统&#xff0c;它将进程…

ASLR和PIE的区别和作用

ASLR和PIE的区别和作用 ASLR的作用 首先ASLR是归属于系统功能的&#xff0c; aslr是一种针对缓冲区溢出的安全保护技术&#xff0c;通过对堆、栈、共享库映射等线性区布局的随机化&#xff0c;通过增加攻击者预测目的地址的难度&#xff0c;防止攻击者直接定位攻击代码位置&…

Linux下关闭ASLR(地址空间随机化)的方法

##0x00 背景知识 ASLR(Address Space Layout Randomization)在2005年被引入到Linux的内核 kernel 2.6.12 中&#xff0c;当然早在2004年就以patch的形式被引入。随着内存地址的随机化&#xff0c;使得响应的应用变得随机。这意味着同一应用多次执行所使用内存空间完全不同&…

ASLR技术

简述 ASLR&#xff08;Address Space Layout Randmoization&#xff0c;地址空间布局随机化&#xff09;是一种针对于缓冲区溢出的安全保护技术。 windows 内核版本 OS内核版本windows 20005.0windows XP5.1windows Server 20035.2windows Vista6.0windows Server 20086.0wi…

ASLR

ASLR 一、ASLR是什么&#xff1f;二、测试ASLR技术1.一个简单的源文件2.生成ALSR.exe与ALSR_no.exe3.使用OllDbg调试器查看程序入口地址与栈地址3.1 ASLR.exe3.2 ASLR_no.exe 4.使用CFF Explorer查看PE文件信息4.1 重定位表的区别4.2 IMAGE_FILE_HEADER/Characteristics属性4.3…

[ASLR,地址空间,Linux,随机化,Windows]ASLR 是如何保护 Linux 系统免受缓冲区溢出攻击的

地址空间随机化&#xff08;ASLR&#xff09;是一种内存攻击缓解技术&#xff0c;可以用于 Linux 和 Windows 系统。了解一下如何运行它、启用/禁用它&#xff0c;以及它是如何工作的。 -- Sandra Henry-stocker 地址空间随机化(Address Space Layout Randomization)&#xff0…

ALSR

一 ALSR介绍&#xff1a; 1.1定义 aslr是一种针对缓冲区溢出的安全保护技术&#xff0c;通过对堆、栈、共享库映射等线性区布局的随机化&#xff0c;通过增加攻击者预测目的地址的难度&#xff0c;防止攻击者直接定位攻击代码位置&#xff0c;达到阻止溢出攻击的目的的一种技…