从网上看了很多资料 ,但是没有能真正帮助我解决TCP粘包的问题的答案。跪求各位高手 ,帮我指点一下 ,最好有源代码和算法 ,让我解决TCP粘包的问题 。谢了 。重谢。

解决方案 »

  1.   

    解决TCP粘包
      

  2.   

    发个伪代码,假设每个包的前两个字节定义了包长,要接收一个完整的包,在接收事件中进行如下处理,采用的SocketAsyncEventArgs,初始设置SetBuffer(0, 2),先接收包的长度部分,同步异步同理。       //接收缓冲区
            byte[] buffers = .......
            void Receive_Completed(object sender, SocketAsyncEventArgs e)
            {
                if (e.SocketError != SocketError.Success)
                {
                    //关闭socket
                    return;
                }
                if (e.LastOperation != SocketAsyncOperation.Receive)
                    return;
                if (e.BytesTransferred == 0)
                {
                    //关闭socket
                    return;
                }
                //接收到的字节数与要接收的长度相同,说明完整接收到了包长部分或者数据部分
                if (e.BytesTransferred == e.Count)
                {
                    //数据包的长度
                    int len = BitConverter.ToInt16(buffers, 0);
                    //接收到的是长度部分
                    if (e.Offset < 2)
                    {
                        //重新设置缓冲区offset,以接收数据部分
                        e.SetBuffer(2, len - 2);
                    }
                    //接收到的是数据部分
                    else
                    {
                        //已经接收到一个完整的包,处理该包
                        //重新设置缓冲区,接收下一个包的包长部分
                        e.SetBuffer(0, 2);
                    }
                }
                //包长部分或者数据部分未完整接收
                else
                {
                    //设置接收缓冲区为剩余长度
                    e.SetBuffer(e.Offset + e.BytesTransferred, e.Count - e.BytesTransferred);
                }
                //进行下一次接收
                socket.ReceiveAsync(e);
            }
      

  3.   


    谢谢。我们不会这个项目是不会考虑用内存做的 。之前看到过一个项目是用内存处理的 ,感觉还不错 。可是如果发生TCP粘包 ,那么你接收到的也还是粘包的数据。我觉得用内存的更大意义是保证数据都可以被处理 。但是对于数据的准确性 ,还要在做处理吧 。不知道我这么看对不对 。是我个人的意见 。
      

  4.   

    解决粘包/半包,指定包头结构 PacketHead : 包长度+包名两种方式处理:
    1、环形缓冲接收
    2、替换接收缓冲区
      

  5.   


    看来.NET里的异步完成端口现在已经很流行了!最近发现很多朋友用这个类来开发网络程序了,要用上了内存池之类的技术就更完美了!楼主朋友其实对TCP协议还不熟,所以对于处理TCP粘包问题很难上手,其实不管TCP怎么粘包数据那数据都还是在那个网络数据流里面的,要看的是楼主怎么到这个流中去取数据,就像上面的这些朋友说的定义包头标识包长度,或是定义结界符、起始符之类等等;我想楼主朋友应该还没亲身体验过“粘包”这个现象吧?如果体验过了应该会更好的了解,那自然解决之道也就出来了,楼主朋友还是多上手吧!
      

  6.   


     #region " 发送包 "
            /// <summary>
            /// 
            /// </summary>
            /// <param name="data">实际发送的数据</param>
            /// <returns>添加包头长度的数据</returns>
            private byte[] SendPack(byte[] data)
            {
                //data长度不能超出65535
                byte[] result = new byte[data.Length + 2];
                BitConverter.GetBytes((UInt16)data.Length).CopyTo(result, 0);
                data.CopyTo(result, 2);
                return result;
            }
            #endregion        #region " 接收包 "
            /// <summary>
            /// 
            /// </summary>
            /// <param name="data">接收到的数据</param>
            /// <returns>粘包的数组,实际发送的数据</returns>
            private List<byte[]> BackPack(byte[] data)
            {
                List<byte[]> result = new List<byte[]>();
                int index = 0;
                do
                {
                    int len = BitConverter.ToUInt16(data, index);
                    index += 2;
                    if (index + len <= data.Length)
                    {
                        byte[] tmp = new byte[len];
                        Array.Copy(data, index, tmp, 0, len);
                        index += len;
                        result.Add(tmp);
                    }
                    else
                    { break; }
                } while (index + 2 < data.Length);
                return result;
            }
            #endregion给你列个最简单的代码.
    发送包前.调用SendPack方法得到发送包.再发送.
    接收包后,调用BackPack方法得到List<byte[]>,这个数据就是有可能粘包的数据,如果不粘包.则仅有一条数据..
      

  7.   

     int len = BitConverter.ToUInt16(data, index); 
    这句认为包头(记录了本包长度)是在data的开始, 一般情况(即没有错误)包头都应该在data的开始, 但如果包头在中间的某个位置该如何查找到包头呢? 比如数据是这样的:
                  ....前一个包的部分数据|包头|....数据....|包头|....后一个包的数据...
    其实就是如何寻找包头的问题...