由于字节流协议具有共同的特点,因此解析也就很简单,主要涉及两种设计模式:模板方法,命令模式。   解析的基本步骤:    1判断一个完整帧的开始,根据协议规定判断帧的开始字节    2获取一个完整的帧。主要有两种,一种是根据根据帧的开始字节结束字节判断一个完整的帧,一种是根据开始帧和帧长度判断    3得到一个完整的帧后,根据命令字创建不同的命令,根据不同的命令字分别处理。    通过模板方法解析帧,由于不同的命令具体组成不一样,所以根据命令字创建不同的命令,使用命令模式,具体处理每一个解析出来的帧。  以下为一个具体的解析例子,只需要简单修改,就可以在实际中使用[csharp] view plaincopypublic class DataProcess  {      protected List fragment = new List();//保存上次处理后,剩余的字节          ///      ///      public void ProcessData(byte[] newReceivedData)      {          try          {              fragment.AddRange(newReceivedData);//把新收到的数据和上次处理的数据合并              var data = new List();              data.AddRange(fragment);              List frames = ParseFrames(data);//解析帧              if (frames.Count > 0)              {                  try                  {                      for (int i = 0; i                    {                          log(string.Format("处理数据:{0}", frames[i]));                          ProcessFrame(frames[i]);//处理帧                      }                      }                  catch (Exception ex)                  {                          throw ex;                  }              }              SaveFragment(data);//保存此次处理后剩余的片段          }          catch (Exception ex)          {              log("处理设备数据出错。");          }      }          ///      ///      ///      protected List ParseFrames(List data)      {          List Frames = new List();          int frameStartIndex = GetFrameStartIndex(data);//判断帧的开始          while (frameStartIndex >= 0)          {              int frameEndIndex = GetFrameEndIndex(data, frameStartIndex);//判断帧的结束              if (frameEndIndex            {                  return Frames;              }              byte[] OneFramebyte = GetOneFrame(data, frameStartIndex, frameEndIndex);              Frames.Add(OneFramebyte);              //data.RemoveRange(0, frameStartIndex);//可以有这一句,避免不完整的帧,对后续解析造成影响              data.RemoveRange(frameStartIndex, frameEndIndex - frameStartIndex);//移除已经处理的数据              frameStartIndex = GetFrameStartIndex(data);          }          return Frames;      }          ///      ///      protected void ProcessFrame(byte[] frame)      {          int commandTypeIndex = 2;//第三个字节规定命令类型          int commandByte = frame[commandTypeIndex];          switch (commandByte) //根据命令的不同,生成的command分别处理,使用命令模式          {              case 1:                  //                  break;              case 2:                  break;              case 3:                  break;          }          }          ///      ///      protected void SaveFragment(List frag)      {          int maxFragmentLength = 1000; //未处理的帧的最大长度          //遗留数据片段过长,有问题。未防止内存压力过大,需要清空fragment          if (frag.Count > maxFragmentLength)          {              frag = new List();          }          fragment.Clear();          fragment.AddRange(frag);          if (frag.Count > 0)          {              log(string.Format("剩余数据片段:{0}", frag));          }          }      灵域www.uy0.net    ///      ///      ///      private static int GetFrameStartIndex(List data)      {          byte FrameStartByte1 = 0x08;          byte FrameStartByte2 = 0x04;          //x8,0x04           for (int i = 0; i        {              if (data[i] == FrameStartByte1 && data[i + 1] == FrameStartByte2) //帧头是0x08,0x04两个字节开始              {                  return i;              }          }          return -1;//默认值,没有找到帧头      }          ///      ///      ///      private static int GetFrameEndIndex(List data, int frameStartIndex)      {          int FrameStartBytesLegnth = 2;//帧头的字节个数          if (frameStartIndex + FrameStartBytesLegnth        {              int length = data[frameStartIndex + 2];//第四个字节规定整个帧的长度              if (length + frameStartIndex            {                  return length + frameStartIndex;              }              return -1;//虽然包含了帧头,但不完整          }          /*  规定了帧的结束字符的情况        for (int i = frameStartIndex + 1; i       {            if (data[i] == 0x08 && data[i + 1] == 0x03) //帧头是0x08,0x03两个字节结束一个完整的帧            {                return i + 1;            }        } */          return -1;//帧不完整      }      ///      ///      ///      ///      ///      private static byte[] GetOneFrame(List data, int frameStartIndex, int frameEndIndex)      {          var OneFramebyte = new byte[frameEndIndex - frameStartIndex];          Array.Copy(data.ToArray(), frameStartIndex, OneFramebyte, 0, frameEndIndex - frameStartIndex);          return OneFramebyte;      }              private static void log(string info)      {          }      }  
10-18 04:27