wyd1520的专栏

我们接收Socket字节流数据一般都会定义一个数据包协议(协议号,长度,内容),由于Socket接收数据是连续的,对方发两个包过来,Socket的 Recive事件有可能只触发一次或触发三次,也就是大家听到的粘包,为解决这个粘包,所以我们必要建一个字节缓冲区,将所有的接收到的字节流全放到这个缓冲区内 由这个缓冲区来分隔每个数据包的内容。

这份代码也是为论坛某个人解决串口接收数据包时而写的。不多说了上代码:

/// <summary>/// 字节缓冲器/// </summary>public class ByteQueue{private List<byte> m_buffer = new List<byte>();public bool Find(){if (m_buffer.Count == 0)return false;int HeadIndex = m_buffer.FindIndex(o => o == 0xAA);if (HeadIndex == -1){m_buffer.Clear();return false; //没找到AA}else if (HeadIndex != 0) //不为开头移掉之前的字节{if (HeadIndex > 1)m_buffer.RemoveRange(0, HeadIndex);}int length= GetLength();if (m_buffer.Count <length){return false;}int TailIndex = m_buffer.FindIndex(o => o == 0x55); //查找55的位置if (TailIndex == -1){//这一步为防止连发一个AA开头的包后,,没发55,而又发了一个AAint head = m_buffer.FindLastIndex(o => o == 0xAA);if (head > -1){m_buffer.RemoveRange(0, head);}return false;}else if (TailIndex + 1 != length) //计算包尾是否与包长度相等{m_buffer.RemoveRange(0, TailIndex);return false;}return true;}/// <summary>/// 命令类型/// </summary>/// <returns></returns>public byte Cmd(){if (m_buffer.Count >= 2){return m_buffer[1];}return 0;}/// <summary>/// 序号/// </summary>/// <returns></returns>public byte Number(){if (m_buffer.Count >= 3){return m_buffer[2];}return 0;}/// <summary>/// 包长度/// </summary>/// <returns></returns>public int GetLength(){int len = 5;//AA 命令类型 序号 校验和 55if (m_buffer.Count >= 3){switch (m_buffer[2]) //第三字节为序号{case 0x00: //序号return len + 16;case 0x01: //序号return len + 10;case 0x02: //序号return len + 12;}}return 0;}/// <summary>/// 提取数据/// </summary>public void Dequeue(byte[] buffer, int offset,int size){m_buffer.CopyTo(0,buffer,offset,size);m_buffer.RemoveRange(0, size);}/// <summary>/// 队列数据/// </summary>/// <param name="buffer"></param>public void Enqueue(byte[] buffer){m_buffer.AddRange(buffer);}}

调用列子:

private ByteQueue queue = new ByteQueue(); private void serialPort1_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可处理同时接收到多个AA … 55 ,AA…55的包{int length = queue.GetLength();byte[] readBuffer = new byte[len];queue.Dequeue(readBuffer, 0, length);OnReceiveData(readBuffer); //<这里自己写一个委托吧就OK了}}}

上面的字节接收容器是用List来处理为方便进出字节后移除整个数据包的字节数据,当然更高效的应用byte[] 数组作成环形缓冲会好很多相对应的写法也会难一些,

偶尔为街头独特的风景驻足,

wyd1520的专栏

相关文章:

你感兴趣的文章:

标签云: