转载连接: http://blog.csdn.net/wyd1520/article/details/44153543
上一篇说到Socket 的字节缓冲区里的 有包头、包长度、包尾,有些数据包只有包头与包尾而里面没有包长度,且这个包头包尾是多个字节组成的。这篇文章也是应CSDN某位网友的需求对这样的数据字节缓冲区进行改造一下,不多说了上代码
- /// <summary>
- /// 字节缓冲器
- /// </summary>
- public class ByteQueue
- {
- private List<byte> m_buffer = new List<byte>();
- private byte[] headBuffer = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xCA, 0xCB, 0xCC, 0xCD }; //包头开始部份
- private byte[] tailBuffer = new byte[] { 0xEA, 0xEB, 0xEC, 0xED };//包结束部份
- private int IndexOf(List<byte> source, byte[] seach, int startIndex)
- {
- string baseStr = BitConverter.ToString(source.ToArray());
- string searchStr=BitConverter.ToString(seach);
- int index= baseStr.IndexOf(searchStr, startIndex);
- return index==-1?-1 : index / 3;
- }
- public bool Find()
- {
- if (m_buffer.Count == 0)
- return false;
- int HeadIndex = IndexOf(m_buffer, headBuffer,0);//找开头的位置
- if (HeadIndex == -1)
- {
- m_buffer.Clear();
- return false; //没找到
- }
- else if (HeadIndex != 0) //不为开头移掉之前的字节
- {
- if (HeadIndex > 1)
- {
- m_buffer.RemoveRange(0, HeadIndex);
- HeadIndex = 0;
- }
- }
- int TailIndex = IndexOf(m_buffer, tailBuffer, headBuffer.Length); //查找结尾的位置
- if (TailIndex == -1)
- {
- //这一步为防止连发一个开头的包后,没发结尾,而又发了一个包头
- int head = IndexOf(m_buffer, headBuffer, 0);
- if (head > -1)
- {
- m_buffer.RemoveRange(0, head);
- }
- return false;
- }
- int packLength = TailIndex - HeadIndex;
- if (packLength<0) //计算包尾是否与包长度相等
- {
- m_buffer.RemoveRange(0, TailIndex + tailBuffer.Length);
- return false;
- }
- return true;
- }
- /// <summary>
- /// 包长度
- /// </summary>
- /// <returns></returns>
- private int GetLength()
- {
- int len = IndexOf(m_buffer, tailBuffer, headBuffer.Length) + tailBuffer.Length; //查找结尾的位置
- return len;
- }
- /// <summary>
- /// 提取数据
- /// </summary>
- public byte[] Dequeue()
- {
- int length = GetLength();
- List<byte> result = m_buffer.Take(length).ToList();//提取数据包
- result.RemoveRange(0, headBuffer.Length);//移掉开头部份 只保留内容
- result.RemoveRange(result.Count - tailBuffer.Length, tailBuffer.Length); //移掉结尾 只保留内容
- m_buffer.RemoveRange(0, length);//缓冲区内容移除
- return result.ToArray();
- }
- /// <summary>
- /// 队列数据
- /// </summary>
- /// <param name="buffer"></param>
- public void Enqueue(byte[] buffer)
- {
- m_buffer.AddRange(buffer);
- }
- }
调用例子:
- public partial class MainForm : Form
- {
- public MainForm()
- {
- InitializeComponent();
- }
- ByteQueue queue = new ByteQueue();
- private void button1_Click(object sender, EventArgs e)
- {
- byte[] buffer = System.Text.Encoding.UTF8.GetBytes(textBox1.Text);
- queue.Enqueue(CreatePack(buffer));
- }
- private void button2_Click(object sender, EventArgs e)
- {
- queue.Enqueue(CreatePack(buffer));
- while (queue.Find())
- {
- byte[] buffer = queue.Dequeue();
- textBox2.Text += System.Text.Encoding.UTF8.GetString(buffer) + "\r\n";
- }
- }
- private byte[] CreatePack(byte[] body)
- {
- byte[] headbuff = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xCA, 0xCB, 0xCC, 0xCD };
- byte[] tailbuff = new byte[] { 0xEA, 0xEB, 0xEC, 0xED };
- byte[] buffer = new byte[headbuff.Length + tailbuff.Length + body.Length];
- Buffer.BlockCopy(headbuff, 0, buffer, 0, headbuff.Length);
- Buffer.BlockCopy(body, 0, buffer, headbuff.Length, body.Length);
- Buffer.BlockCopy(tailbuff, 0, buffer, headbuff.Length + body.Length, tailbuff.Length);
- return buffer;
- }
- }
放到串口或Socke的例子:
- private ByteQueue queue = new ByteQueue();
- private void socket_DataReceived(object sender, SerialDataReceivedEventArgs e)
- {
- int len = serialPort1.BytesToRead;
- if (len > 0)
- {
- byte[] temp = new byte[len];
- serialPort1.Read(temp, 0, len);
- queue.Enqueue(temp);
- while (queue.Find()) //while可处理同时接收到多个包
- {
- byte[] readBuffer = queue.Dequeue();
- OnReceiveData(readBuffer); //<这里自己写一个委托吧就OK了
- }
- }
- }