Socket 字节缓冲区第二种方式
2015-03-09 13:06
246 查看
上一篇说到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);
}
}
调用例子:
放到串口或Socke的例子:
/// <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了 } } }
相关文章推荐
- Socket 字节缓冲区第二种方式
- Socket接收字节缓冲区
- 网络(4):socket中用户自定义缓冲区的原因及方式
- socket中用户自定义缓冲区的原因及方式
- Socket缓冲区探讨,是否有拆包的方式?
- Socket接收字节缓冲区
- Linux socket默认缓冲区的配置文件
- 非阻塞方式下Socket读取数据的一个例子
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)
- 【Linux】管道容量及缓冲区的存储方式
- java网络编程(一) socket方式TCP和Datagram的UDP
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)
- socket tcp缓冲区大小的默认值、最大值
- [原]OpenGL基础教程(五)缓冲区数据更新方式
- Io流字节字符流九种方式读取和写入总结!
- RIL层传输的方式就是socket
- 关于arm处理器 内存编址模式 与 字节对齐方式 (转)
- 关于socket的读取的方式
- linux下socket connect 阻塞方式 阻塞时间控制
- (笔记)Socket设置非阻塞方式