异步接收数据都正常,是个定长TLV包,但是接收到后都是直接写入bufflist后再getdata出来处理,发现有时会有掉包情况,以为是线程安全问题,后来加入了lock段将bufflist内代码锁住,依然会有掉包现象,导致组包失败,请教了一些人,回答仍然是线程安全问题,请问是否有更好的处理办法,如有请贴出代码,因为理论我都明白,也不是解包问题(这个解包方式只是随便写的简单方式)现需要能实际解决缓存数据包问题的方法                        user.BuffList.InsertByteArray(data); //插入数据包缓冲池
                        do
                        {
                            try
                            {
                                byte[] buff = user.BuffList.GetData(); //取出存在的数据包
                                if (buff == null)
                                    break;
                                DataHandler(buff, user); //将每个数据包指令进行处理
                            }
                            catch
                            {
                                //取包异常
                            }
                        } while (true);    public class BuffList
    {
        public object locklist = new object();        public List<byte> ByteList { get; set; }        public BuffList()
        {
            ByteList = new List<byte>();
        }        public void Clecr()
        {
            lock (locklist)
            {
                ByteList.Clear();
            }
        }        public void InsertByteArray(byte[] Data)
        {
            lock (locklist)
            {
                ByteList.AddRange(Data);
            }
        }        public Int16 readint16wgh()
        {
            byte[] temp = new byte[2];
            ByteList.CopyTo(0, temp, 0, 2);
            return BitConverter.ToInt16(temp, 0);
        }        public enum CmdType
        {
            XXX = 1101,
        }        public byte[] GetData()
        {
            lock (locklist)
            {
                if (ByteList.Count > 288)
                {
                    if ((CmdType)readint16wgh() == CmdType.XXX)
                    {
                        byte[] temp = new byte[289];
                        ByteList.CopyTo(0, temp, 0, 289);
                        if (packet.CheckWGHData(temp))
                        {
                            ByteList.RemoveRange(0, 289);
                            return temp;
                        }
                    }
                    else
                    {                        //包异常,无法正确解析
                        
                    }
                    return null;
                }
                else
                {
                    return null;
                }
            }
        }
    }

解决方案 »

  1.   

    接收到数据后,异步处理,你是异步接收的,然后再次加个异步回调处理,我先前就是这样处理的,就没有问题,现在用Delphi开发了,没有那个代码了
      

  2.   

    我现在就是异步接收异步回调,关键是我这个缓存机制还是存在线程安全问题,每秒大概100个数据包左右,数据包输入回调是个委托,我记得系统会跟据某些机制开出一条或者更多线程处理这些数据,如果是那样的话,就会有可能多于一条线程进行insert操作,那么就会导致数据包乱序,但是我已加入lock锁,依然有问题
      

  3.   

    1、发送端发送数据间隔时间长些;
    2、接收端用链表接收,边接收边处理数据,接收时Add新数据,处理完毕Delete旧数据
      

  4.   

    兄弟,你没看我代码,已是边接收边处理数据,已是接收时add,处理完毕deltete...........关键是我上面说的,线程安全问题
      

  5.   

    不加lock也会包乱序,我是刚开始没加,出现包乱序,现在加了,仍然包乱序
      

  6.   

    我不知道逗在哪?我也不是什么高手。如果你很高手就直接给出方法好了。以下是我写的关socket的接收,委托部分,至于抄?微软官方有SocketAsyncEventArgs例子,一步一样自己看而我帖子的第一段代码就是在InputHandler函数内        public delegate void InputHandler(byte[] data, SocketAsyncEventArgs socketAsync);        public InputHandler Input { get; set; }        void BeginReceive(SocketAsyncEventArgs e)
            {
                if (e.SocketError == SocketError.Success&&e.BytesTransferred>0)
                {
                    byte[] data = new byte[e.BytesTransferred];                Array.Copy(e.Buffer, e.Offset, data, 0, data.Length);                if (this.Input != null)
                        this.Input.BeginInvoke(data, e, RecevieCallBack, Input);                if (!e.AcceptSocket.ReceiveAsync(e))
                    {
                        BeginReceive(e);
                    }
                }
             }
      

  7.   

    不是,长连接,局域网内,没断过,包乱序是我观察后得出的结果,不一定正确,但问了一些人,大多数都认为是因为BuffList的线程安全问题。因为我也不确定BeginInvoke(data, e, RecevieCallBack, Input)后是不是一定是单线程。如果不是的话,是否就有可能导致前面的还没写入,后面的先写入了,导致了包乱序。
      

  8.   

    我不太清楚你所说的承担责任,我理解是socket本身作为主线程时只需负责好握手,收,发这些基本就好,怎么处理收到的数据,和怎么组成数据发出去都应该由其他来处理,以达到最优化,或许是错的,或许是每个人的理解不一样吧
      

  9.   

    你所看到的"掉包"现象实际上是异步调试出现的问题,实际上包的顺序是对的
    建议你仔细检查下GetData()函数,再组包的时候是否情况都考虑到了
      

  10.   

    刚刚开始学习socket,来关注一下。
      

  11.   


     user.BuffList.InsertByteArray(data); //插入数据包缓冲池
    加上互斥
    类似生产者与消费者问题
      

  12.   

    确实是异步调用出现的问题,是类似多线程读写的问题,就是说insert数据时,有可能有多于一个异步调用,有可能刚好第二条线程先获取了锁先写了进去,如果不用这种异步调用而用阻塞调用,直接BeginReceive中处理是可以解决这个问题,但是这样无论是效率还是本身架构上都显得不合适。
      

  13.   

    你是指在使用 user.BuffList.InsertByteArray(data)时互斥?你说的我可以试试,但我觉得不一定行,因为异步调用Input函数时,Input函数本身是否只在一个线程上工作?如果不在是否会互斥?因为这个方式和我在Bufflist内函数加互斥似乎是一样的,我在BuffList.InsertByteArray(data)内部insert时已经加了锁,看代码 public void InsertByteArray(byte[] Data)
            {
                lock (locklist)
                {
                    ByteList.AddRange(Data);
                }
            }按道理来说,如果在需要执行BuffList.InsertByteArray(data)时加锁可以的话,那么当其执行InsertByteArray函数本身时就已经有互斥锁机制了。
      

  14.   

    我们写过类似的代码基本问题都出在处理上而不是想象中的线程问题(我们也是这么猜想的) 后来用了笨办法 在处理过程中添加写LOG 对照LOG测试处理中的问题 如果你还没解决这个问题 建议尝试下
      

  15.   

    可能原因、包发太快、n包同时到达
    方案一:包与包之间暂停一下下:sleep时间自测罗
    方案二:序列化后自己加上包长度、收到包后解出包长度、如果有多的就是下一个包、可就解出下一包、不可就等下一个数据、合包解包、方案一比较简单
      

  16.   

    发包时断点、看序列化后的大小、
    收包后、在断点、看收包后的大小、
    看size有没有一样、
    过大就是包挤在一块
      

  17.   

    1.Socket .Accept
    判断Socket.Connect
    true就接收,结束后到1
    false就循环到1
      

  18.   

    用live555时碰到丢包的情况(udp),主要原因是数据量比较大(几路8M的视频流),socket的接收和发送缓存用了默认的8K,改大后就不怎么出现丢包了。不知道楼主是否有可能是这个原因