您的位置:首页 > 其它

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);
}
}

调用例子:
 

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了
}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: