异步Socket接收数据后缓存处理问题

路遥迢 2011-06-29 12:27:09
异步接收数据都正常,是个定长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;
}
}
}
}
...全文
702 37 打赏 收藏 转发到动态 举报
写回复
用AI写文章
37 条回复
切换为时间正序
请发表友善的回复…
发表回复
匹夫 2013-07-02
  • 打赏
  • 举报
回复
用live555时碰到丢包的情况(udp),主要原因是数据量比较大(几路8M的视频流),socket的接收和发送缓存用了默认的8K,改大后就不怎么出现丢包了。不知道楼主是否有可能是这个原因
绿领巾童鞋 2011-12-05
  • 打赏
  • 举报
回复
1.Socket .Accept
判断Socket.Connect
true就接收,结束后到1
false就循环到1
bei0305 2011-12-04
  • 打赏
  • 举报
回复
兄弟你问题解决了吗?
strife013 2011-07-06
  • 打赏
  • 举报
回复
看看看看
alexccmm 2011-07-04
  • 打赏
  • 举报
回复
发包时断点、看序列化后的大小、
收包后、在断点、看收包后的大小、
看size有没有一样、
过大就是包挤在一块
dai78 2011-07-04
  • 打赏
  • 举报
回复
交互模式收发
alexccmm 2011-07-04
  • 打赏
  • 举报
回复
可能原因、包发太快、n包同时到达
方案一:包与包之间暂停一下下:sleep时间自测罗
方案二:序列化后自己加上包长度、收到包后解出包长度、如果有多的就是下一个包、可就解出下一包、不可就等下一个数据、合包解包、

方案一比较简单
萨拉嘿 2011-07-03
  • 打赏
  • 举报
回复
[Quote=引用 27 楼 hudingwen 的回复:]
引用 24 楼 oonukeoo 的回复:
你所看到的"掉包"现象实际上是异步调试出现的问题,实际上包的顺序是对的。。。
建议你仔细检查下GetData()函数,再组包的时候是否情况都考虑到了

确实是异步调用出现的问题,是类似多线程读写的问题,就是说insert数据时,有可能有多于一个异步调用,有可能刚好第二条线程先获取了锁先写了进去,如果不用这种异步调用而用阻塞调用,直接BeginRe……
[/Quote]
我们写过类似的代码。。。基本问题都出在处理上而不是想象中的线程问题(我们也是这么猜想的) 后来用了笨办法 在处理过程中添加写LOG 对照LOG测试处理中的问题 如果你还没解决这个问题 建议尝试下
路遥迢 2011-07-02
  • 打赏
  • 举报
回复
有无高手呀~随便指点指点呀
freemangood 2011-07-01
  • 打赏
  • 举报
回复
刚刚开始学习socket,来关注一下。
路遥迢 2011-07-01
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 tyler3180 的回复:]
user.BuffList.InsertByteArray(data); //插入数据包缓冲池
加上互斥
类似生产者与消费者问题
[/Quote]
你是指在使用 user.BuffList.InsertByteArray(data)时互斥?你说的我可以试试,但我觉得不一定行,因为异步调用Input函数时,Input函数本身是否只在一个线程上工作?如果不在是否会互斥?因为这个方式和我在Bufflist内函数加互斥似乎是一样的,我在BuffList.InsertByteArray(data)内部insert时已经加了锁,看代码

public void InsertByteArray(byte[] Data)
{
lock (locklist)
{
ByteList.AddRange(Data);
}
}

按道理来说,如果在需要执行BuffList.InsertByteArray(data)时加锁可以的话,那么当其执行InsertByteArray函数本身时就已经有互斥锁机制了。
路遥迢 2011-07-01
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 oonukeoo 的回复:]
你所看到的"掉包"现象实际上是异步调试出现的问题,实际上包的顺序是对的。。。
建议你仔细检查下GetData()函数,再组包的时候是否情况都考虑到了
[/Quote]
确实是异步调用出现的问题,是类似多线程读写的问题,就是说insert数据时,有可能有多于一个异步调用,有可能刚好第二条线程先获取了锁先写了进去,如果不用这种异步调用而用阻塞调用,直接BeginReceive中处理是可以解决这个问题,但是这样无论是效率还是本身架构上都显得不合适。
萨拉嘿 2011-07-01
  • 打赏
  • 举报
回复
你所看到的"掉包"现象实际上是异步调试出现的问题,实际上包的顺序是对的。。。
建议你仔细检查下GetData()函数,再组包的时候是否情况都考虑到了
tyler3180 2011-07-01
  • 打赏
  • 举报
回复

user.BuffList.InsertByteArray(data); //插入数据包缓冲池
加上互斥
类似生产者与消费者问题
路遥迢 2011-07-01
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 sp1234 的回复:]
这也太面向了吧?如果你在另一个线程中处理,你不承担责任吗?
[/Quote]
我不太清楚你所说的承担责任,我理解是socket本身作为主线程时只需负责好握手,收,发这些基本就好,怎么处理收到的数据,和怎么组成数据发出去都应该由其他来处理,以达到最优化,或许是错的,或许是每个人的理解不一样吧
路遥迢 2011-07-01
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 ulihss 的回复:]
你包乱序是不是因为你的连接是不是断断续续的??
[/Quote]
不是,长连接,局域网内,没断过,包乱序是我观察后得出的结果,不一定正确,但问了一些人,大多数都认为是因为BuffList的线程安全问题。因为我也不确定BeginInvoke(data, e, RecevieCallBack, Input)后是不是一定是单线程。如果不是的话,是否就有可能导致前面的还没写入,后面的先写入了,导致了包乱序。
路遥迢 2011-07-01
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 sp1234 的回复:]
引用 2 楼 hudingwen 的回复:

已分开,你看到的这些代码都是接收后委托了另一个线程进行处理的,也就是说我贴出来的代码都是在另一条线程上,但是不一定是一条线程,系统处理不过来时可能会大于一条线程


你太逗了,这个怎么能“委托了另一个线程进行处理”呢?真是咄咄怪事。我是想不出来,除非你只是为了追时髦,或者你的整个接受代码都是抄别人的。
[/Quote]
我不知道逗在哪?我也不是什么高手。如果你很高手就直接给出方法好了。

以下是我写的关socket的接收,委托部分,至于抄?微软官方有SocketAsyncEventArgs例子,一步一样自己看

而我帖子的第一段代码就是在InputHandler函数内

public delegate void InputHandler(byte[] data, SocketAsyncEventArgs socketAsync);

public InputHandler Input { get; set; }

void BeginReceive(SocketAsyncEventArgs e)
{
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);
}
}
}
hdw163 2011-06-30
  • 打赏
  • 举报
回复
帮顶,望有高手
Kobayashi 2011-06-30
  • 打赏
  • 举报
回复
你包乱序是不是因为你的连接是不是断断续续的??
  • 打赏
  • 举报
回复
这也太面向了吧?如果你在另一个线程中处理,你不承担责任吗?
加载更多回复(17)

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧