首页 > 其他分享 >Socket接收粘包处理

Socket接收粘包处理

时间:2024-01-21 14:11:08浏览次数:30  
标签:packetRecvLen Socket int 粘包 byte 接收 buff

什么是粘包?

比如:通过Socket发2条不一样长度的数据,"abc"和"defg"。因为Socket的数据不是你请求发就立即发送的,有时候为了减少网络交互次数,会把几小的个数据凑一凑一起发送。

如果前面的被凑到一起发送了"abcdefg",就出现了粘包。

 

如何解决粘包问题?

发送数据的时候,在数据里带上这个数据的长度信息,这样就算多个数据被凑在一起发送,我们也能根据每个数据的长度信息来把他们区分出来。

上面的数据就变成:3abc,4defg;其中:3表示3个字节,utf-8字符串abc占3个字节;4表示4个字节。

 

代码 

private const int Packet_Head_Len = 4; //包头4字节, 一个int

private void RecvLoop(Socket socket)
{
    byte[] buff = new byte[8 * 1024]; //假设单个数据包不会超过这个大小
    byte[] temp4Bytes = new byte[4];
    int packetRecvLen = 0;
    while (true)
    {
        try
        {
            int buffRemainLen = buff.Length - packetRecvLen;
            if (buffRemainLen <= 0) //数据包超过buff的大小了
                break;

            int recvLen = socket.Receive(buff, packetRecvLen, buffRemainLen, 0, out var errCode);
            if (0 == recvLen) //服务端把该连接Shutdown或Close了
                break;

            packetRecvLen += recvLen;
            if (IsPacketReady(packetRecvLen, buff, temp4Bytes, out var bodyLen))
            {
                var str = Encoding.UTF8.GetString(buff, Packet_Head_Len, bodyLen);
                //todo: 数据包处理

                packetRecvLen -= Packet_Head_Len; //包头
                packetRecvLen -= bodyLen; //下一个包的数据

                if (packetRecvLen > 0) //如果有下一个包的数据, 移到buff开头
                    Buffer.BlockCopy(buff, Packet_Head_Len + bodyLen, buff, 0, packetRecvLen);
            }
        }
        catch (Exception ex)
        {
            //todo: 打印错误信息
        }
    }
}

//检查数据是否都已经接收到了
public static bool IsPacketReady(int packetRecvLen, byte[] buff, byte[] temp4Bytes, out int bodyLen)
{
    bodyLen = 0;
    if (packetRecvLen < Packet_Head_Len) 
        return false;

    Buffer.BlockCopy(buff, 0, temp4Bytes, 0, 4);
    bodyLen = BitConverter.ToInt32(temp4Bytes, 0);
    if (packetRecvLen < Packet_Head_Len + bodyLen)
        return false;

    return true;
}

 

标签:packetRecvLen,Socket,int,粘包,byte,接收,buff
From: https://www.cnblogs.com/sailJs/p/17977800

相关文章

  • Java21 + SpringBoot3集成WebSocket
    目录前言相关技术简介什么是WebSocketWebSocket的原理WebSocket与HTTP协议的关系WebSocket优点WebSocket应用场景实现方式添加maven依赖添加WebSocket配置类,定义ServerEndpointExporterBean定义WebSocketEndpoint前端创建WebSocket对象总结前言近日心血来潮想做一个开源项目,目......
  • Android连接socket
    本文章主要是写Android作为客户端。Android客户端对于Android客户端,我们需要创建一个Socket对象,并指定服务器的IP地址和端口号。然后,使用Socket对象的connect()方法连接到服务器。连接成功后,可以使用Socket对象发送和接收数据。但其中一个比较重要的点是要使用到多线程,因为Andr......
  • TCP三次握手源码分析(服务端接收ACK&TCP连接建立完成)
    内核版本:Linux3.10内核源码地址:https://elixir.bootlin.com/linux/v3.10/source(包含各个版本内核源码,且网页可全局搜索函数)《TCP三次握手源码分析(客户端发送SYN)》《TCP三次握手源码分析(服务端接收SYN以及发送SYN+ACK)》《TCP三次握手源码分析(客户端接收SYN+ACK以及发送ACK......
  • hyperexpress框架/使用uwebsockets.js核心
    import{scheduleJob}from'node-schedule';//定时任务functionsetupScheduledTasks(){//每6秒执行一次setInterval(()=>{taskEverySixSeconds();},6000);//每33分钟执行一次setInterval(()=>{taskEve......
  • I/O多路复用与socket
    前言简单来讲I/O多路复用就是用一个进程来监听多个文件描述符(fd),我们将监听的fd通过系统调用注册到内核中,如果有一个或多个fd可读或可写,内核会通知应用程序来对这些fd做读写操作,select、poll、epoll都是用于处理此类问题的系统API,只不过注册和调用的方式略有不同。例如telnet命......
  • uWebSockets.js 框架经验
    目录结构project/│├──src/│├──app.ts│├──routes/││├──userRoutes.ts││└──index.ts│├──entities/││└──User.ts│├──utils/││└──parseQuery......
  • 解决前端传递日期参数后端接收报错问题
    当controller中的方法直接用参数接收前端传递的参数时日期格式不匹配会报如下错误:Failedtoconvertvalueoftype'java.lang.String'torequiredtype'java.util.Date';,就是说类型转换异常@PostMapping("/1")publicStringdoSign1(LonguserId,DatesignDate){S......
  • fastapi接收图片文件
    #api接口,主函数importbase64importioimportcv2importosimporttimefromPILimportImageimportnumpyasnpfromfastapiimportFastAPI,HTTPExceptionimportuvicornapp=FastAPI()##############################################@app.post("/upload......
  • qt和java的socket连接
    事先说明qt为客户端(发出请求)java为服务端(处理请求)关于qt的客户端来说我们大体上要完成三个需求,即请求连接,发送,接收请求连接如果想使用qt写socket程序,首先需要在.pro文件中添加QT+=network;(非常非常重要)接收然后我们就可以在代码中使用QT的网络库了,socket涉及到的函数库......
  • C# 中,可以使用 System.Net.Sockets 命名空间中的 UdpClient 类来发送和接收 UDP 数据
    C#中,可以使用System.Net.Sockets命名空间中的UdpClient类来发送和接收UDP数据报文。以下是一个简单的C#示例,演示如何使用UDP发送和接收数据:点击查看代码usingSystem;usingSystem.Net;usingSystem.Net.Sockets;classProgram{staticvoidMain(){......