【飞秋】TCP粘包

ScanNet数据集详解 ScanNet 是一个 RGB-D 视频数据集,在超过 1500 次扫描中包含了 250 万个视图,并标注了 3D 相机位姿、表面重建和实例级的语义分割。为了收集这些数据,设计了一个易于使用且具有扩展性的 RGB-D 捕获系统,包括自动化的表面重建和众包的语义标注。如果您想下载 ScanNet 数据,请使用您的机构邮箱地址填写一份 ScanNet 使用条款协议,并发送至 scannet@googlegroups.com。压缩包是将3D的标注信息“拍扁”成2D图片的结果,对应原始视频的每一帧。 阅读详情

 首先申明一下,写的这个东西注重的是一个思想~,代码只是参考,并不能直接运行.下面进入正题

这两天在弄Silverlight版本的SOCKET网络编程,参考了菩提树下的杨过的例子,写了一段程序

自己也遇到了一些问题,例如TCP协议的粘包,想了个解决方案,兴冲冲的,GOOGLE了一下发现类似的思想很多,不过决定还是把代码贴出来吧

 

   /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="msgOrSql">消息类容</param>
        /// <returns></returns>
        public bool MsgTo(MsgOrSql msgOrSql)
        {
            try
            {
                SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
                MemoryStream ms = new MemoryStream();
                byte[] dataLen = new byte[sizeof(long)];
                ms.Write(dataLen, 0, dataLen.Length);//先占住前八位字符


                string jsonString = JsonConvert.SerializeObject(msgOrSql);//JSON的序列化方式,读者也可以用其它的序列化方式
                byte[] msgByte = Encoding.UTF8.GetBytes(jsonString);//写入需要的流
                ms.Write(msgByte,0,msgByte.Length);

                ms.Position = 0;//从头写
                dataLen = BitConverter.GetBytes(ms.Length - dataLen.Length);//有效长度
                ms.Write(dataLen,0,dataLen.Length);// 将有效长度写入流中

                byte[] data = ms.ToArray();//需要发送的字节流
                ms.Close();            
                socketEventArg.SetBuffer(data,0,data.Length);
                socketEventArg.RemoteEndPoint = clickSocket.RemoteEndPoint;
                clickSocket.SendAsync(socketEventArg);
            }
            catch (Exception ee)
            {
                Console.Write(ee);
            }
            return false;
        }

以上是发送代码,下面贴一下接收方的代码

 

    private int msgLength;//消息总长
        private int yishouLength;//已收消息长度
        byte[] lstReceiveBytes = new byte[] { };//已经接受的数据

    /// <summary>
        /// 接受服务端发来的数据-回调处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnSocketReceiveCompleted(object sender, SocketAsyncEventArgs e)
        {
            if (e.Buffer == null)
            {
                return;
            }
            MemoryStream ms = new MemoryStream();
            if (lstReceiveBytes.Length == 0)//判断缓存是否存在数据
            {

      //缓存中没有数据
                msgLength = int.Parse(BitConverter.ToInt64(e.Buffer, 0).ToString());//获得数据长度,也就是发送端写入的字符长度

                ms.Write(e.Buffer, 8, e.BytesTransferred - 8);//将剩余的字符流写入缓存,除了长度字符之外,所以是从第八位开始读取数据流的
            }
            else
            {

      //缓存中有数据了
                ms.Write(lstReceiveBytes,0,lstReceiveBytes.Length);//将原有的数据写入缓存
                ms.Write(e.Buffer, 0, e.BytesTransferred);//将当前接收数据写入缓存
            }
            yishouLength += e.BytesTransferred;//已收数据长度+=当前收的数据长度
            lstReceiveBytes = ms.ToArray();//缓存中的数据替换
            ms.Close();
            GetMsgByByte();//调用处理缓存数据的方法
            try
            {
                //继续异步地从服务端 Socket 接收数据(类似长连接)
                if (clickSocket != null && clickSocket.Connected)
                {
                    clickSocket.ReceiveAsync(e);
                }
                else
                {
                    Console.Write("无法连接到服务器...请刷新后再试...");
                }
            }
            catch (Exception ex)
            {
                Console.Write(ex.Message.ToString());
            }

        }
        private void GetMsgByByte()//处理缓存数据的方法
        {
            try
            {
                if (lstReceiveBytes.Length >= msgLength) //如果已接受的数据长度大于等于定义的数据长度 也就是说可以处理一条消息了
                {

       byte[] msgByte = new byte[] { };//当前需要处理的包信息
                    msgByte = lstReceiveBytes;//默认为缓存中的信息
                    if (lstReceiveBytes.Length > msgLength) //处于粘包状态
                    {

         //将字符流分为两个部分,一部分为当前的一条消息,分离出来当前处理,另一部分为下一步操作的数据流,写入缓存进行下一步操作,(或许写的有点模糊)   

         MemoryStream m = new MemoryStream();
                        m.Write(lstReceiveBytes,0,msgLength);//取字符流中的一条传送完毕的消息
                        msgByte = m.ToArray();
                        m.Close();
                        m = new MemoryStream();
                        m.Write(lstReceiveBytes, msgLength, lstReceiveBytes.Length - msgLength);//根据当前的数据长度读取一条数据,所属的所有字符流
                        byte[] bb = m.ToArray();
                        msgLength = int.Parse(BitConverter.ToInt64(bb, 0).ToString());//获得下一条信息的字符流的长度

                        m.Close();
                        m = new MemoryStream();
                        m.Write(lstReceiveBytes, msgLength, lstReceiveBytes.Length - msgLength);//获得下一条信息的字符流,(不包含长度的字符流)

                        lstReceiveBytes = m.ToArray();//替换缓存中的数据
                        m.Close();

             }
                    string jsonString = Encoding.UTF8.GetString(lstReceiveBytes.ToArray(), 0, msgLength);//JSON的序列化方式,大家可以不用理会
                    MsgOrSql msgOrSql = new MsgOrSql();
                    msgOrSql = JsonConvert.DeserializeObject<MsgOrSql>(jsonString);
                    if (msgOrSql.dbInfo != null)
                    {
                        if (msgOrSql.dbInfo.FangFaMin != null)
                        {
                            DBHelper.listDbInfo.Add(msgOrSql.dbInfo.FangFaMin, msgOrSql.dbInfo);
                        }
                    }
                    if (msgOrSql.msgInfo != null)
                    {
                        if (msgOrSql.msgInfo.Id != null)//发送者的ID不为空
                        {
                            UserHelper.listMsg.Add(msgOrSql.msgInfo);
                        }
                    }
                    if (lstReceiveBytes.Length > msgLength)
                    {
                        GetMsgByByte();//递归调用处理字符流的方法
                    }else

       {

         return; 

       }

       //字符流处理完毕,初始化接受消息的一些信息
                    msgLength = 0;
                    yishouLength = 0;
                    lstReceiveBytes=new byte[0];
                }
               
            }
            catch (Exception ex)
            {
                Console.Write(ex);
            }


        }

两个方法,一个是接受的回调函数,另外一个是处理字符流的方法

 

代码写的可能有些问题,COPY下去也运行不了,不过主要的思想应该是表现出来了,相信有些功底的人都能看得懂

发送消息之前,将消息打包,消息头之前添加该消息的字符长度,接收方接受消息之后根据字符长度,判断消息是否处理完毕,如果出现粘包,则继续根据下一条消息的长度,处理下一条消息

 

希望对读者有所启发吧

关注技术文章飞秋:http://www.freeeim.com/,24小时专业转载。

【VxWorks】Vxworks、QNX、Xenomai、Intime、Sylixos、Ucos等实时操作系统的性能特点 VxWorks 操作系统是美国WindRiver公司于1983年设计开发的一种嵌入式实时操作系统,是嵌入式开发环境的关键组成部分。其内核支持多任务调度(采用基于优先级抢占方式,同时支持同优先级任务间的分时间片调度)、任务间的同步、进程间通信机制、中断处理、定时器和内存管理机制等,且提供了一个快速灵活的与 ANSIC 兼容的 I/O 系统,网络支持 对其它VxWorks系统和TCP/IP网络系统的"透明"访问。具有良好的持续发展能力、良好的可靠性、卓越的实时性和高性能的内核以及友好的用户开发环境。 阅读详情

相关推荐

GEO芯片数据下载和探针ID转换(保姆级教程)

R语言安装、GEO芯片数据下载、探针ID转换

qq_43138237的博客 3万+

Socket的监听的三种方式

首先要打开监听 Listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); IPEndPoint hostEntry = new IPEndPoint(getLocalmachineIPAddress(), Serve...

bajinge6197的博客 1000

三. zemax光学设计流程+案例

文章目录zemax 基本操作:1. 建立光学基本模型2. 像质评价3. 优化(重点)4. 公差分析简单镜头设计 zemax 基本操作: 1. 建立光学基本模型 2. 像质评价 3. 优化(重点) 对系统设定的约束条件或目标值 统称为操作数。 操作数: 光学特性参数(焦距EFFL,近轴放大率PMAG,入瞳位置EMPP) 像差参数(球差SPHA,彗差COMA,像散ASTI) 边界条件(中心厚度值CTVA,边缘厚度值ETAV) 优化的主要步骤: 设置评价函数和优化操作数 一般小像差系统采用波像差 构建

Taiiiii的博客 8058

TCP粘包

首先申明一下,写的这个东西注重的是一个思想~,代码只是参考,并不能直接运行.下面进入正题 这两天在弄Silverlight版本的SOCKET网络编程,参考了菩提树下的杨过的例子,写了一段程序 自己也遇到了一些问题,例如TCP协议的粘包,想了个解决方案,兴冲冲的,GOOGLE了一下发现类似的思想很多,不过决定还是把代码贴出来吧    /// <summary>...

dielu5148的博客 208

Windows升级保留个人文件和应用灰色?改注册表版本指纹

Windows 升级安装并非简单跳过下一步,安装程序会先读取注册表中 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion 下的 EditionID、ProductName、CompositionEditionID 等版本指纹,与目标镜像 install.wim/esd 记录的版本类型做双向匹配。若当前系统被识别为 LTSC、精简版或跨版本降级,兼容性扫描会判定升级路径不可用,于是“保留个人文件和应用”变灰,只能全新安装。理解版本指纹与升级可行性表的匹配机制,可

weixin_31986143的博客 378

学习笔记:物理信息神经网络(PINN)

PINN 的强大在于它打破了传统数值方法的限制,将神经网络的非线性拟合能力与物理方程的严谨性结合起来。它在处理高维、数据稀缺、复杂物理约束的场景下尤其出色。当然,PINN 也有收敛慢、梯度消失等挑战,比如,复杂 PDE 可能导致梯度传播困难,收敛慢(梯度消失)、于具有快速变化特征的系统,如冲击波,标准 PINN 可能精度不足,需要改进策略,比如自适应采样或多尺度特征提取。但随着研究深入,这些问题正在不断被解决。物理或化学方程为什么往往是偏微分方程?什么是物理信息神经网络(PINN)?x_%7Bi%7D。

qq_52635735的博客 1万+

TCP粘包和拆包

简介​ TCP是个流协议,在TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓存区的实际情况进行包的划分。所以在业务上,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送。这就是TCP的粘包Sticky和拆包unpacking in。 TCP粘包 拆包发生的原因 应用程序writ...

测试 644

《AFSim 2.9中文参考手册》

本栏目将对《AFSim 2.9中文参考手册》进行持续更新,欢迎关注交流!对本文或者AFSIM相关内容感兴趣的朋友,可私心联系作者。《AFSim 2.9中文参考手册》内容概览。

henggesim的博客 1万+

C#高性能大容量SOCKET并发(二):SocketAsyncEventArgs封装

SocketAsyncEventArgs是微软提供的高性能异步Socket实现类,主要为高性能网络服务器应用程序而设计,主要是为了避免在在异步套接字 I/O 量非常大时发生重复的对象分配和同步。

SQLDebug_Fan的专栏 6万+

Git下载与安装

一、Git下载 二、Git安装

欢迎订阅我的“JAVA全栈开发笔记(全)”专栏,价格优惠,仅需19.9元。 6万+

Python爬虫实战:股票历史数据抓取与量化回测全流程详解

我们以**东方财富网(eastmoney.com)和雪球网(xueqiu.com)**为主要目标,演示如何爬取A股历史行情。最常用的HTTP请求库,简单易用,适合静态页面数据请求。本文详细介绍了从股票历史数据抓取到简单回测的完整流程,代码示例基于最新技术,结构清晰,适合初学者和进阶者学习量化投资实战。希望对你入门Python爬虫和量化交易有所帮助!

2201_76125261的博客 1782

TCP协议-TCP粘包问题

一、前言 我们知道,TCP是一个面向字节流的传输层协议。“流” 意味着 TCP 所传输的数据是没有边界的。这不同于 UDP 协议提供的是面向消息的传输服务,其传输的数据是有边界的。TCP 的发送方无法保证对方每次收到的都是一个完整的数据包。于是就有了粘包、拆包问题的出现。粘包、拆包问题只发生在TCP协议中。 二、什么是粘包、拆包? 假设客户端向服务器连续发送了两个数据包,用 packet1 和 packet2 来表示,那么服务端收到的数据可以分为下面三种情况: 第一种情况,接收端正常...

yunfan 1万+

SAP FICO CBS接口-银企直连付款平台功能开发说明书(包括测试样例、FS)

SAP FICO CBS接口-银企直连付款平台功能开发说明书(包括测试样例、FS)

我好像病了的博客 2450

TCP粘包原因及解决办法

1、粘包的概念 粘包:多个数据包被连续存储于连续的缓存中,在对数据包进行读取时由于无法确定发生方的发送边界,而采用某一估测值大小来进行数据读出,若双方的size不一致时就会使指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。 2、出现粘包的原因 出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能由接收方造成。 发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通

c++小白的博客 1万+

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

TCP粘包,拆包及解决方法

在进行Java NIO学习时,发现,如果客户端连续不断的向服务端发送数据包时,服务端接收的数据会出现两个数据包粘在一起的情况,这就是TCP协议中经常会遇到的粘包以及拆包的问题。我们都知道TCP属于传输层的协议,传输层除了有TCP协议外还有UDP协议。那么UDP是否会发生粘包或拆包的现象呢?答案是不会。UDP是基于报文发送的,从UDP的帧结构可以看出,在UDP首部采用了16bit来指示UDP数据报文...

沉迷代码无法自拔 2万+

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

tcp 粘包问题及其解决

TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输协议,它保证了数据的可靠性和顺序性。TCP粘包是指在TCP协议中发送方发送的若干个小数据包在接收方接收时被合并成一个大数据包的现象,或者多个大数据包在接收时被分割成若干个小数据包的现象。这种现象的产生是因为TCP协议中的流控制和数据传输机制。

你好 1713

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

什么是TCP粘包?

讲一下OSI七层模型? OSI七层模型最终并没有成为广为使用的标准模型。可能是OSI的专家缺乏实际经验,OSI标准制定周期过长,按OSI标准生产的设备无法及时进入市场,OSI模型设计的并不合理,一些功能在多层中重复出现等原因造成的。除了标准的OSI七层模型以外,常见的网络层次划分还有TCP/IP四层协议以及TCP/IP五层协议,它们之间的对应关系如下图所示: 网络协议有几层?分别是什么? https://t.im/m89k 为什么要将数据切片? 软件是属于应用层上的。 消息在进入传输层时使用的是传输

u013343616的博客 5748

QTcpSocket 及 TCP粘包分析

~~~~我的生活,我的点点滴滴!!

破茧 9308

什么是TCP粘包?怎么解决这个问题

在socket网络编程中,都是端到端通信,由客户端端口+服务端端口+客户端IP+服务端IP+传输协议组成的五元组可以明确的标识一条连接。在TCP的socket编程中,发送端和接收端都有成对的socket。发送端为了将多个发往接收端的包,更加高效的的发给接收端,于是采用了优化算法(Nagle算法),将多次间隔较小、数据量较小的数据,合并成一个数据量大的数据块,然后进行封包。那么这样一来,接收端就必须...

weixin_41047704的博客 7万+

TCP如何解决粘包

如何解决粘包? 粘包的问题出现是因为不知道一个用户消息的边界在哪,如果知道了边界在哪,接收方就可以通过边界来划分出有效的用户消息。 一般有三种方式分包的方式: 固定长度的消息; 特殊字符作为边界; 自定义消息结构。 #固定长度的消息 这种是最简单方法,即每个用户消息都是固定长度的,比如规定一个消息的长度是 64 个字节,当接收方接满 64 个字节,就认为这个内容是一个完整且有效的消息。 但是这种方式灵活性不高,实际中很少用。 #特殊字符作为边界 我们可以在两个用户消息之间插入一个特殊的字符

居老师的博客 7010

网络编程:TCP粘包问题——各层粘包/拆包、Nagle 算法、Go实现长度字段协议解决TCP粘包、使用TCP的应用层协议设计

需要注意的是,即使是连续发送大量数据,在正常的网络环境和合理的数据处理方式下,TCP通常可以保持数据包的完整性和顺序,不会出现粘包。当发送方过于迅速发送数据而使接收方无法跟上或处理不当,此时**可能**发生粘包问题。注意,TCP粘包问题并非TCP协议设计上的缺陷,而是由于TCP协议的数据传输特性和网络条件的影响所致。解决TCP粘包问题通常需要应用层协议设计或使用特定的数据分隔方式来确的数据传输和解析。长度字段协议(Length-Field Protocol):发送方在每个数据包前部添加一个表示数据包长度的字

Pistachiout的学习博客 4575

TCP粘包问题处理

这篇记录TCP通信粘包问题的处理方法。以上就是处理粘包问题的一种方法,使用async_read一次性读完一整个消息头部和一整个消息体,这样就做到把粘在一起数据读的时候分开了。

2201_75528880的博客 1679

Tcp粘包分析

使用过TCP的通信的都可能会遇到这样的问题,代码写的没有问题,但是每次接收到的数据总是怪怪的。有时候接受的长,有时候接收到的数据又比较短。反正数据就是得不到正确的解析,接下来我们分析一下究竟是什么原因导致的?又应该如何解决呢?最后作者还想补充一点关于http协议如何解决TCP粘包问题。

C_J_L12580的博客 1448

TCP 粘包/拆包

TCP的粘包和拆包问题往往出现在基于TCP协议的通讯中,比如RPC框架、Netty等TCP 粘包/拆包 就是你基于 TCP 发送数据的时候,出现了多个字符串“粘”在了一起或者一个字符串被“拆”开的问题。TCP粘包和拆包是指在使用TCP协议进行数据传输时,发送方发送的数据包与接收方接收的数据包之间出现了不符合预期的粘连或拆分情况。TCP粘包:TCP粘包指的是发送方在一次发送中将多个逻辑上独立的数据包粘合成一个大的数据包发送,而接收方可能会将这个大的数据包误认为是多个小的数据包。

刘皇叔说Java的博客 2016

TCP粘包是什么?如何处理?UDP有粘包吗?

文章目录1.什么是TCP粘包2.出现粘包的原因3.粘包的处理- 什么时候需要处理- 如何处理4.UDP没有粘包 1.什么是TCP粘包 TCP粘包就是指发送方发送的若干包数据到达接收方时粘成了一包,从接收缓冲区来看,后一包数据的头紧接着前一包数据的尾,出现粘包的原因是多方面的,可能是来自发送方,也可能是来自接收方。 2.出现粘包的原因 出现粘包的原因是多方面的,可能是来自发送方,也可能是来自接收方。...

nigar_的博客 2726
上一篇: 【飞秋】Android开发——NDK开发入门
下一篇: 【飞秋】SQL Server性能调教系列(4)--Profiler(上)
普通网友
博客等级 码龄22年 1万+粉丝 3156原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值