异步接收数据都正常,是个定长TLV包,但是接收到后都是直接写入bufflist后再getdata出来处理,发现有时会有掉包情况,以为是线程安全问题,后来加入了lock段将bufflist内代码锁住,依然会有掉包现象,导致组包失败,请教了一些人,回答仍然是线程安全问题,请问是否有更好的处理办法,如有请贴出代码,因为理论我都明白,也不是解包问题(这个解包方式只是随便写的简单方式)现需要能实际解决缓存数据包问题的方法 user.BuffList.InsertByteArray(data); //插入数据包缓冲池
do
{
try
{
byte[] buff = user.BuffList.GetData(); //取出存在的数据包
if (buff == null)
break;
DataHandler(buff, user); //将每个数据包指令进行处理
}
catch
{
//取包异常
}
} while (true); public class BuffList
{
public object locklist = new object(); public List<byte> ByteList { get; set; } public BuffList()
{
ByteList = new List<byte>();
} public void Clecr()
{
lock (locklist)
{
ByteList.Clear();
}
} public void InsertByteArray(byte[] Data)
{
lock (locklist)
{
ByteList.AddRange(Data);
}
} public Int16 readint16wgh()
{
byte[] temp = new byte[2];
ByteList.CopyTo(0, temp, 0, 2);
return BitConverter.ToInt16(temp, 0);
} public enum CmdType
{
XXX = 1101,
} public byte[] GetData()
{
lock (locklist)
{
if (ByteList.Count > 288)
{
if ((CmdType)readint16wgh() == CmdType.XXX)
{
byte[] temp = new byte[289];
ByteList.CopyTo(0, temp, 0, 289);
if (packet.CheckWGHData(temp))
{
ByteList.RemoveRange(0, 289);
return temp;
}
}
else
{ //包异常,无法正确解析
}
return null;
}
else
{
return null;
}
}
}
}
do
{
try
{
byte[] buff = user.BuffList.GetData(); //取出存在的数据包
if (buff == null)
break;
DataHandler(buff, user); //将每个数据包指令进行处理
}
catch
{
//取包异常
}
} while (true); public class BuffList
{
public object locklist = new object(); public List<byte> ByteList { get; set; } public BuffList()
{
ByteList = new List<byte>();
} public void Clecr()
{
lock (locklist)
{
ByteList.Clear();
}
} public void InsertByteArray(byte[] Data)
{
lock (locklist)
{
ByteList.AddRange(Data);
}
} public Int16 readint16wgh()
{
byte[] temp = new byte[2];
ByteList.CopyTo(0, temp, 0, 2);
return BitConverter.ToInt16(temp, 0);
} public enum CmdType
{
XXX = 1101,
} public byte[] GetData()
{
lock (locklist)
{
if (ByteList.Count > 288)
{
if ((CmdType)readint16wgh() == CmdType.XXX)
{
byte[] temp = new byte[289];
ByteList.CopyTo(0, temp, 0, 289);
if (packet.CheckWGHData(temp))
{
ByteList.RemoveRange(0, 289);
return temp;
}
}
else
{ //包异常,无法正确解析
}
return null;
}
else
{
return null;
}
}
}
}
2、接收端用链表接收,边接收边处理数据,接收时Add新数据,处理完毕Delete旧数据
{
if (e.SocketError == SocketError.Success&&e.BytesTransferred>0)
{
byte[] data = new byte[e.BytesTransferred]; Array.Copy(e.Buffer, e.Offset, data, 0, data.Length); if (this.Input != null)
this.Input.BeginInvoke(data, e, RecevieCallBack, Input); if (!e.AcceptSocket.ReceiveAsync(e))
{
BeginReceive(e);
}
}
}
建议你仔细检查下GetData()函数,再组包的时候是否情况都考虑到了
user.BuffList.InsertByteArray(data); //插入数据包缓冲池
加上互斥
类似生产者与消费者问题
{
lock (locklist)
{
ByteList.AddRange(Data);
}
}按道理来说,如果在需要执行BuffList.InsertByteArray(data)时加锁可以的话,那么当其执行InsertByteArray函数本身时就已经有互斥锁机制了。
方案一:包与包之间暂停一下下:sleep时间自测罗
方案二:序列化后自己加上包长度、收到包后解出包长度、如果有多的就是下一个包、可就解出下一包、不可就等下一个数据、合包解包、方案一比较简单
收包后、在断点、看收包后的大小、
看size有没有一样、
过大就是包挤在一块
判断Socket.Connect
true就接收,结束后到1
false就循环到1