我写了一个上位机程序,来接收W5500模块发送的数据(1/50K秒,发送16bit数据),发送接收到的数据会有丢包,用wireshark进行抓包后也证实了丢包的问题,如下图所示下面是我接收端的程序
 private void Receive()
        {
            byte[] buff = new byte[8 * 1024];   
            byte[] dataSave = new byte[1 * 1024 * 1024];
            int count = 0;
            string path = frm.path+"\\"+ "789.txt";
            while (true)
            {
                if (flag)
                {
                    Array.Clear(buff, 0, buff.Length);
                    int recv = SockClient.ReceiveFrom(buff, ref IP);
                    if (count + recv < dataSave.Length)
                        Array.Copy(buff, 0, dataSave, count, recv);
                    else
                    {
                        Array.Copy(buff, 0, dataSave, count, dataSave.Length - count);
                        break;
                    }
                    count += recv;
                }
                else //阻塞当前线程
                {
                    wh.WaitOne();
                }
            }
            write2Disk(dataSave, path);
        }请问出现丢包的问题是我接收端程序的问题吗,应该怎样修改才能不丢包。

解决方案 »

  1.   

    不允许丢包的情况,一般采用TCP通讯协议,TCP经常会出现粘包现象,通常做法是做长度校验,每个包加入包长,一般占用2个byte用short表示,接收方收到包以后先计算包长,在截取包长字节数存储,接收到的包长如果小于包长,则继续接收,如果大于包长,则截取包长数据存储,剩余字节数缓存到下一次读取,依次循环
      

  2.   

    1.udp本身是无法保证数据不丢失的。
    如果要可靠,换tcp
    2.建议使用异步方式接收,自己使用同步来
    实现异步模式效率不高。
    3.数据接收和解析推荐分离。
      

  3.   

    您好,我这个是用TCP来发送和接收的,而且我接收端的处理是接受完1M的数据就停止接收然后进行保存,接收到的数据与wireshark抓包的数据都是一致的,就是在之前的wireshark截图中的红色部分就是发送端TCP发送失败的情况,我就是想问下如果用异步的方式来接收是否能够解决这个问题
      

  4.   

    换成异步接收之后发现还是有丢包的问题,不过效果比同步接收的好一点,这里我贴一下我的代码,请大家看看有没有能够改进的地方。这里也是接收到dataSave长度的数据后就停止接收,并进行保存。
    public void AsynReceive()
            {
                NetworkStream stream = tcp.GetStream();
                Array.Clear(buff, 0, buff.Length);
                stream.BeginRead(buff, 0, buff.Length, asyncResult =>
                {
                    int len = stream.EndRead(asyncResult);
                    if (count + len < dataSave.Length)
                    {
                        Array.Copy(buff, 0, dataSave, count, len);
                        count += len;
                        AsynReceive();
                    }
                    else
                    {
                        tcp.Close();
                        write2Disk(dataSave, path);
                        return;
                    }
                }, stream);
            }
      

  5.   

    用while循环来接收很不好。用4楼的方法,异步+递归调用。另外,需要解包和重新组包。因为tcp有粘包的问题。