110,536
社区成员
发帖
与我相关
我的任务
分享
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了
}
}
}
[/quote]
如果我用的是 socket.BeginReceive(_recvDataBuffer, 0, _recvDataBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveData), client); 那么这个该怎么办?ByteQueue queue = new ByteQueue();
try
{
int port = 4001;
string host = "192.168.0.80";
IPAddress ip = IPAddress.Parse(host);
IPEndPoint ipe = new IPEndPoint(ip, port);//把ip和端口转化为IPEndPoint实例
Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建一个Socket
Console.WriteLine("Conneting...");
c.Connect(ipe);//连接到服务器
string recvStr = "";
byte[] recvBytes = new byte[1024];
int bytes;
bytes = c.Receive(recvBytes, recvBytes.Length, 0);//从服务器端接受返回信息
if (bytes > 0)
{
byte[] temp = new byte[bytes];
queue.Enqueue(temp);
while (queue.Find()) //while可处理同时接收到多个包
{
byte[] readBuffer = queue.Dequeue();
}
}
c.Close();
}
catch (ArgumentNullException e)
{
Console.WriteLine("ArgumentNullException: {0}", e);
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
Console.Read();
queue.Enqueue(temp);
while (queue.Find()) //while可处理同时接收到多个包
{
byte[] readBuffer = queue.Dequeue();
OnReceiveData(readBuffer); //<这里自己写一个委托吧就OK了
}
就这个了,你放到Socket接收的那个代码中
就是int length=socket.Recive(xxx,xxxx) 的后面呀,至于同步异步,看你自己写的接收方式与这个缓冲器没关系的。你只管把Socket收到的内容向里面放就是了,他就能逐个解析出包
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了
}
}
}
/// <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);
return baseStr.IndexOf(searchStr, startIndex) / 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 delegate void OnMessageEventHandler(NetworkStream stream, string message);
修改为public delegate void OnMessageEventHandler(NetworkStream stream, byte[] message);
来抛出二进制数据消息,而不需要考虑字符串编码。
不过,通常如果设计一个比较高级(特别是面向可读字符串)的协议,例如基于json的协议,不但更容易调试,也更容易动态扩展消息内容。面向byte[ ]来设计,看似通用,实则影响了许多子系统的应用扩展能力。