如题。对方发过来的数据包的长度不固定,有时候108字节,有时候180字节,有时候36字节,有时候。。
以前数据包长度固定的时候,我定义的接收字节数据为
    private static byte[] byteAll = new byte[198];  
    private static byte[] crc = new byte[4]; 
代码是
socket.Bind(iep);
socket.Listen(150);
newSocket = socket.Accept();
while (true)
  {
     newSocket.Receive(byteAll);
     Array.Copy(byteAll, 0, bytes, 0, 194); 
     Array.Copy(byteAll, 8, crc, 0, 4);
...........现在发送过来的包长度不固定,我也不知道怎么定义接收时候的字节数组长度了,截取的时候也不知道从哪里开始截取了,怎么办呢。
谢谢,在线等。
                  

解决方案 »

  1.   

    定义一个协议,参考
    http://blog.csdn.net/jq_whh/article/details/6560711
      

  2.   


    此类问题LZ并未想清楚到底是为什么会时而长度108,时而长度180。
    为什么会出现这种长度不固定的情况,那是因为网络问题。
    接收不定长度的数据包是需要有一个包头的,前4字节是整个数据包的长度描述。这个是发送端自定义的协议。
       public override ReplyMessage Read(Stream stream)
            {
                ReplyMessage reply = new ReplyMessage();            byte[] nFileLenBytes = new byte[4];
                stream.Read(nFileLenBytes, 0, nFileLenBytes.Length);
                int len = BitConverter.ToInt32(nFileLenBytes, 0);
                reply.Length = len;            byte[] buffer = new byte[0];            while (len > 0 && stream.CanRead)
                {
                    byte[] readBytes = new byte[102400];
                    int recv = stream.Read(readBytes, 0, readBytes.Length);
                    len -= recv;                if (recv < 102400)
                    {
                        //小于指定长度的包,根据接收的实际长度清除空字节。
                        byte[] m_readBytes = new byte[recv];
                        System.Buffer.BlockCopy(readBytes, 0, m_readBytes, 0, recv);
                        readBytes = m_readBytes;
                    }
                    int newLen = buffer.Length + readBytes.Length;
                    byte[] newBuffer = new byte[newLen];
                    System.Buffer.BlockCopy(buffer, 0, newBuffer, 0, buffer.Length);
                    System.Buffer.BlockCopy(readBytes, 0, newBuffer, buffer.Length, recv);
                    buffer = newBuffer;                System.Threading.Thread.Sleep(1);
                }
                reply.Buffer = buffer;            return reply;
            }
      

  3.   


    发过来的数据包是这样的,包括数据包长度 
    指令状态  :STATUS1 = 0xBB
    设备地址  :假设为 0xC6 0x83 0x6E 0x70
    数据包长度:0x00 0xC6
    DATA1 ~ 180 
    校验码    :0xD6 0x72 0x48 0xF8
    具体数据如下:
    0x5A 0xA5 0x69 0x96 0xBB 0x00 0x00 0x00 0xC6 0x83 
    0x6E 0x70 0x00 0xC6 0x02 0x37 0x37 0x20 0x33 0x39 
    0x20 0x2d 0x37 0x31 0x20 0x34 0x36 0x30 0x30 0x30 
    0x20 0x32 0x35 0x30 0x32 0x20 0x34 0x34 0x36 0x44 
    0x20 0x37 0x20 0x33 0x20 0x33 0x33 0x20 0x2d 0x39 
    0x36 0x20 0x32 0x35 0x20 0x20 0x20 0x20 0x20 0x03 
    0x45 0x52 0x52 0x4f 0x52 0x20 0x43 0x4f 0x44 0x45 
    0x3a 0x20 0x30 0x20 0x20 0x20 0x20 0x20 0x20 0x20 
    0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 
    0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 
    0x20 0x20 0x20 0x20 0x07 0x45 0x52 0x52 0x4f 0x52 
    0x20 0x43 0x4f 0x44 0x45 0x3a 0x20 0x30 0x20 0x20 
    0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 
    0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 
    0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x0C 
    0x37 0x37 0x20 0x34 0x30 0x20 0x2d 0x37 0x30 0x20 
    0x34 0x36 0x30 0x30 0x30 0x20 0x32 0x35 0x30 0x32 
    0x20 0x34 0x34 0x36 0x44 0x20 0x37 0x20 0x33 0x20 
    0x33 0x33 0x20 0x2d 0x39 0x36 0x20 0x32 0x36 0x20 
    0x20 0x20 0x20 0x20 0xD6 0x72 0x48 0xF8
      

  4.   

     比如你收到:0x05 0x37, 0x36, 0x32, 0x20, 0x33, 0x36, 0x20, 0x2d, 0x37, 0x34, 0x20, 0x34, 0x36, 0x30, 0x30, 0x30, 0x20, 0x32, 0x35, 0x30, 0x32, 0x20, 0x35, 0x41, 0x34, 0x33, 0x20, 0x34, 0x20, 0x31, 0x20, 0x33, 0x30, 0x20, 0x2d, 0x31, 0x30, 0x33, 0x20, 0x32, 0x39, 0x20, 0x20, 0x20, 0xd4
    除了第一个表示编号5,其它当文本显示就是:762 36 -74 46000 2502 5A43 4 1 30 -103 29 这个是怎么转换的呢
      

  5.   

    有协议就好办了,这是数据流协议,按照分组读取就行了:
    这应该是数据包起始标识:0x5A 0xA5 0x69 0x96
    指令状态 :STATUS1 = 0xBB
    保留:0x00 0x00 0x00 
    设备地址 :0xC6 0x83 0x6E 0x70
    数据包长度:0x00 0xC6
    数据:后面读取0x00c6个字节
    校验:
    后面就是第二个数据包,再搜索0x5A 0xA5 0x69 0x96就可以了
    如果遇到上面的这种情况,可以把数据丢弃,准备搜索起始标识。
      

  6.   


    那接收的byte[]长度定义为多少呢。以前数据包长度固定的时候,我定义的接收字节数据为
      private static byte[] byteAll = new byte[198];   
    完全占满,现在他不固定,定义多少字节长度呢,定义多了有空字节,定义少了接收不完
      

  7.   

    接收数据时可以分两步进行
    1、把接收到的数据全部放到一个先入先出堆栈
    2、从堆栈中读取数据包,
       通常把数据包格式定义成一个类,每个字段作为一个成员变量,根据数据包的实际数据填写,
       byteAll 可以根据长度字段来定义
       
      

  8.   

    这时的byteAll 应该是指数据包中的纯数据
      

  9.   

    数据包长度:0x00 0xC6楼主朋友,这里不是明确了包长度的字节吗?只要找到这个字节并读取后,知道了长度后直接读取这个长度的数据不就行了?如果长度和实际内容不一样,那么表示还没接收完,则先把这一段数据暂时存放在别的地方,继续接收下一段数据,没接收完的数据就在这一段里面,接收完这一段后再和之前的数据合并起来就行了,不过你最好判断一下这一段数据里是否还有0x00 0xC6(数据包长度值),如果有的话便又是另一段数据的开始!