• SOCKET TCP 粘包及半包问题


    大家在使用SOCKET通信编程的时候,一般会采用UDP和TCP两种方式;TCP因为它没有包的概念,它只有流的概念,并且因为发送或接收缓冲区大小的设置问题,会产生粘包及半包的现象。

    场景:

    服务端向连续发送三个“HelloWorld”(三次消息无间隔),那么客户端接收到的情况会有以下三种:

    1)HelloWorld  HelloWorld  HelloWorld  (客户端接收三次)

    2)HelloWorldHelloWor  ldHelloWorld    (客户端接收两次)

    3)HelloWorldHelloWorldHelloWorld      (客户端接收一次)

    我们这里不详细讨论这些情况是如何产生的(博客园相关的文章有很多,大家不清楚的可以去查一查),我以自己的方式来描述一下如何处理粘包、半包的消息。

    1)不要使消息产生粘包、半包现象

    这个我是这样做的:把每个包的大小固定,并且把发送缓冲区和接收缓冲区的大小都设置成包的大小(这个做法也许是不成熟的,但我试验下来,还是比较有效而且高效的,希望有其它更好处理方式的人可以指正)

    2)把消息进行包装,根据外部包装特性来剥出每一个粘在一起的消息

    比如,发送HelloWorld,在HelloWorld外套个壳,变成<msg>HelloWorld</msg>,那么这个时候可能会收到这样的一个包:<msg>HelloWorld</msg><msg>HelloWorld</msg><msg>Hello和另一个这样的包World</msg>,我是以最简单的方式,把这两个消息加工成三个HellWorld,请看代码:

    //这是暂存上一个消息中不完整的消息内容
    
    private string halfMsg = "";
    private void ReceiveCallback(IAsyncResult AR)
    {
      try
      {
        int REnd = sckClient.EndReceive(AR);
        //上次未处理的消息内容+本次接收到的内容
        string temp = halfMsg + Encoding.Default.GetString(msgBuffer, 0, REnd); 
        //使用正则来提取消息内容
        string pattern = "^<msg>.*?</msg>";
        //循环提取,直到剩下的消息是不完整的数据(或刚好全部提取完)
        while(Regex.IsMatch(temp, pattern))
        {
          string match = Regex.Match(temp, pattern).Groups[0].Value;
          temp = temp.Remove(0,match.Length);
        }
        //将正则循环提取后剩下的内容暂存(可能为空串)
        halfMsg = temp;
                                    
        msgBuffer = new byte[128];
        //同时接收客户端回发的数据,用于回发
        sckClient.BeginReceive(msgBuffer, 0, msgBuffer.Length, 0, new AsyncCallback(ReceiveCallback), null);   
      }   
      catch (Exception ex)   
      {     
        msgBuffer = new byte[128];     
        sckClient.BeginReceive(msgBuffer, 0, msgBuffer.Length, 0, new AsyncCallback(ReceiveCallback), null);   
      } 
    } 
    

      

    大家不喜勿喷,此篇文章的主要目的是给自己做个笔记,如能帮到一些后来人,那当然是极好的事情了。

  • 相关阅读:
    Centos7.2 下搭建LNMP环境(终极版)Yum安装
    ThinkPHP3.2 插入数据库数据,缓存问题
    无限极分类的JS实现
    PHP 商城无限极分类
    高速下载Centos的地址
    高性能的城市定位API接口
    阿帕奇配置本地虚拟站点,XAMPP环境下
    Nginx 下配置Laravel 错误404
    laravel Redis缓存
    pytest.1.快速开始
  • 原文地址:https://www.cnblogs.com/liu2008hz/p/3755101.html
Copyright © 2020-2023  润新知