zoukankan      html  css  js  c++  java
  • 粘包分包现象及处理


    现象描述


    由于TCP协议本身的机制

    客户端与服务器会维持一个连接发送数据


    粘包原因

    如果发送的网络数据包太小,TCP则会合并较小的数据包再发送,

    接收端便无法区分哪些数据是发送端自己分开的,

    因此便会产生粘包现象。

    或者,接收端把数据放到接收缓冲区中,

    如果数据没有及时从缓冲区取走,

    下次取数据时就可能出现一次取走多个数据包的情况。

    如:

    客户端Send:hello

    客户端Send:unity

    服务端Recv:Recv


    分包原因

    如果发送的数据包太大,TCP有可能会将它拆分成多个包发送

    接收端的一次Receive可能只收到一部分数据。

    如:

    客户端Send:hellounity

    服务端Recv:hel

    服务端Recv:lounity


    处理办法


    每个数据包前加上长度字节


    如果缓冲区的数据长度大于要提取的字节数

    则取出相应的字节

    否则等待下一次数据接收


    代码实现


    private void ProcessData(Conn conn) {
             //小于字节长度
             if (conn.buffCount < sezeof(Int32))
                 return;
             
             //消息长度
             Array.Copy(conn.readBuff,conn.lenBytes,sizeof(Int32));
             conn.msgLength = BitConverter.ToInt32(conn.lenBytes,0);
             if(conn.buffCount < conn.msgLength + sizeof(Int32))
                 return;
                 
             //处理消息
             string str = System.Text.Encoding.UTF8.GetString(conn.readBuff,sizeof(Int32),conn.msgLength);
             Console.WriteLine("收到消息["+conn.GetAdress() + "]" + str);
             Send(conn,str);
             
             //清除已处理的消息
             int count = conn.buffCount - conn.msgLength = sizeof(Int32);
             Array.Copy(conn.readBuff,sizeof(Int32) + conn.msgLength,conn.readBuff,0,count);
             conn.buffCount = count;
             if(conn.buffCount > 0){
                 ProcessData(conn);
             }
    }


    当然,这段代码是无法直接复制粘贴使用的

    因为里面涉及到了很多其他的API

    在这里只需要了解实现的方式即可

  • 相关阅读:
    SAP一些学习网址
    Silverlight RIA Servcie 删除子对象实体提交错误的问题[解决]
    Clean up your BizTalk databases
    Silverlight RIA Service开发实战总结(一)
    Silverlight ToolKitAutoCompleteBox bug(Style bug)
    domaincontext load 回调
    数据驱动开发For Silverlight WCF RIA1.0 三步曲
    xpath 查询忽略大小
    代码重构之没有理由拒绝Lambda表达式
    离写出大师级代码只差这一步
  • 原文地址:https://www.cnblogs.com/fws94/p/7127552.html
Copyright © 2011-2022 走看看