zoukankan      html  css  js  c++  java
  • Socket解决粘包问题2

    在AsynServer中对接收函数增加接收判断,如果收到客户端发送的请求信息,则发送10个测试包给发送端,否则继续接收,修改后的接收代码如下:

            private void AsynReceive()
            {
                byte[] data = new byte[1024];//接收缓存
                string receiveStr;
                string[] sendArr = PackageBuilder.BuildPackage(10);//生成发送数组,10个包
                socket.BeginReceive(data, 0, data.Length, SocketFlags.None, asyncResult => {
                    int length = socket.EndReceive(asyncResult);
                
                    receiveStr = Encoding.ASCII.GetString(data, 0, length);//获取缓存中的信息
                                                                           //    Console.WriteLine(receiveStr);
    
                    if (receiveStr == "1")      //标志字符'1',如果收到1,则发送测试包给客户端,如果不是1,继续接受
                    {
                        for (int i = 0; i < 10; i++)
                        {
                            Console.WriteLine("第{0}次发送:",i);
                            AsynSend(sendArr[i]);
                       //     Thread.Sleep(200);
                        }
    
                    }
                    else
                        AsynReceive();
                }, null);
    
    
            }
    View Cosde

    其中if (receiveStr == "1")是接收判断,如果收到客户端发来的1,则发送测试包给客户端,如果不是1,继续接收。因为是异步发送,所以Console.WriteLine("第{0}次发送:",i);显示可能和发送数据不同步,但肯定是发送了10次。

    测试一下,发送10次,接收端收到结果如下:

    发了10次,而只收了8次,从上图中我们可以发现第6次和第7次发生了粘包,两个包被当作1个包接收了,如果你编写解包程序时不考虑粘包,那么解包循环在第7次解包时会抛异常。当然一种快捷的避免粘包方式是在发送函数的 AsynSend(sendArr[i]);下面加上Thread.Sleep(200);减少发送频率,但这不是长久之计,接下来我们进入客户端来处理粘包问题。

    客户端主要是修改了SyncReceive方法,使用StringBuilder来做接收,因为StringBuilder较于string而言,增加字符串,删除字符串的效率比较高,代码如下:

     string[] receiveArr = new string[10];//用于存储接收到的数据
            int arri=0;//数组位序
            public virtual void SyncReceive()
            {
                //StringBuilder sb = new StringBuilder(1024*1024);
                StringBuilder receiveSb = new StringBuilder();      //接收字符串buffer
                string receiveStr;            //解包过程中用于 中间处理  
                int index;       //位序,用于解包
                int dataLength; //存储接收包中的数据长度
                int i = 0;
                Thread th = new Thread(() =>
                {
                    while (receiveFlag)
                    {
                        byte[] buffer = new byte[1024];
                        int r = socket.Receive(buffer);
                        string str = Encoding.ASCII.GetString(buffer, 0, r);    //只是用来显示
                        Console.WriteLine("第{0}次收到数据:{1}",i++,str);
                        Console.WriteLine();
    
                        receiveSb.Append(str);              //存储接收字符串,可能存多个包
                        receiveStr = receiveSb.ToString();
                        index = receiveStr.IndexOf("data:");//可能有多个"data"
    
                        while (index > 1)
                        {
                            dataLength = int.Parse(receiveStr.Substring(index - 2, 2));//数据长度规定为2个字节
                            receiveArr[arri] = receiveStr.Substring(index, dataLength);//保存数据到数组中
                            Console.WriteLine("保存的数据数组[{0}]:{1}",arri,receiveArr[arri++]);
                            receiveSb.Remove(0, 10 + dataLength);//包头+数据长度字节共10个字节"HEAD|H1|38",后面是数据"data:xxxxxxxxxxxxxxxxxxxx"
                            receiveStr = receiveSb.ToString();
                            index = receiveStr.IndexOf("data:");//寻找下一个"data",如果没有跳出循环
                        }
                      
                      
                            //sb.AppendFormat("{0}", Encoding.ASCII.GetString(buffer, 0, r));
                        }
                });
                th.Start();
               
            }
    View Code

    方法上面加了两个全局变量,receiveArr是一个数组,用于保存接收到的实时数据,这些数据可以用于前台展示,也可以直接保存到数据库;arri是数组位序,运行结果如下:

    如图所示,客户端接收了7次数据,第一次有4个包粘在了一起,但我们通过合适的解包,依然将10次数据分开保存在字符串数组中。

    客户端要先发送"1"标志给客户端才能执行上面的程序,     SynSend("1");

    程序的源码下载地址:

    链接:http://pan.baidu.com/s/1nvfa8lF 密码:zjoa

    粘包的处理是比较简单的,更麻烦的是分包,虽然不常见,但也要考虑,后面考虑做一下分包的处理,程序写的比较毛糙,如有不足之处希望大家指出。

  • 相关阅读:
    【流量劫持】SSLStrip 终极版 —— location 瞒天过海
    【流量劫持】沉默中的狂怒 —— Cookie 大喷发
    【流量劫持】SSLStrip 的未来 —— HTTPS 前端劫持
    Web 前端攻防(2014版)
    流量劫持 —— 浮层登录框的隐患
    流量劫持能有多大危害?
    流量劫持是如何产生的?
    XSS 前端防火墙 —— 整装待发
    XSS 前端防火墙 —— 天衣无缝的防护
    XSS 前端防火墙 —— 无懈可击的钩子
  • 原文地址:https://www.cnblogs.com/gongheng/p/5699092.html
Copyright © 2011-2022 走看看