异步接收数据都正常,是个定长TLV包,但是接收到后都是直接写入bufflist后再getdata出来处理,发现有时会有掉包情况,以为是线程安全问题,后来加入了lock段将bufflist内代码锁住,依然会有掉包现象,导致组包失败,请教了一些人,回答仍然是线程安全问题,请问是否有更好的处理办法,如有请贴出代码,因为理论我都明白,也不是解包问题(这个解包方式只是随便写的简单方式)现需要能实际解决缓存数据包问题的方法
-
C# code
-
user.BuffList.InsertByteArray(data); // 插入数据包缓冲池 do { try { byte[] buff = user.BuffList.GetData(); // 取出存在的数据包 if (buff == null) break; DataHandler(buff, user); // 将每个数据包指令进行处理 } catch { // 取包异常 } } while ( true);
-
C# code
-
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; } } } }
bdmh
2011-06-29 12:34:37
2011-06-29 12:34:37
建议,把接收和数据处理分开,接收后放到列表中,单独线程对列表逐个处理
hudingwen
2011-06-29 12:39:13
2011-06-29 12:39:13
已分开,你看到的这些代码都是接收后委托了另一个线程进行处理的,也就是说我贴出来的代码都是在另一条线程上,但是不一定是一条线程,系统处理不过来时可能会大于一条线程
hudingwen
2011-06-29 13:46:22
2011-06-29 13:46:22
哪位兄弟有解决方法呀
djc7811
2011-06-29 13:50:33
2011-06-29 13:50:33
接收到数据后,异步处理,你是异步接收的,然后再次加个异步回调处理,我先前就是这样处理的,就没有问题,现在用Delphi开发了,没有那个代码了
hudingwen
2011-06-29 14:03:15
2011-06-29 14:03:15
我现在就是异步接收异步回调,关键是我这个缓存机制还是存在线程安全问题,每秒大概100个数据包左右,数据包输入回调是个委托,我记得系统会跟据某些机制开出一条或者更多线程处理这些数据,如果是那样的话,就会有可能多于一条线程进行insert操作,那么就会导致数据包乱序,但是我已加入lock锁,依然有问题
djc7811
2011-06-29 14:13:12
2011-06-29 14:13:12
1、发送端发送数据间隔时间长些;
2、接收端用链表接收,边接收边处理数据,接收时Add新数据,处理完毕Delete旧数据
2、接收端用链表接收,边接收边处理数据,接收时Add新数据,处理完毕Delete旧数据
hudingwen
2011-06-29 14:15:26
2011-06-29 14:15:26
兄弟,你没看我代码,已是边接收边处理数据,已是接收时add,处理完毕deltete...........关键是我上面说的,线程安全问题
djc7811
2011-06-29 14:17:23
2011-06-29 14:17:23
不要加Lock
hudingwen
2011-06-29 14:18:40
2011-06-29 14:18:40
不加lock也会包乱序,我是刚开始没加,出现包乱序,现在加了,仍然包乱序
hudingwen
2011-06-29 14:34:35
2011-06-29 14:34:35
哪位兄弟有解决方法呀
hudingwen
2011-06-29 15:07:17
2011-06-29 15:07:17
哪位兄弟有解决方法呀
hdw163
2011-06-30 12:43:15
2011-06-30 12:43:15
帮顶,望有高手
hudingwen
2011-06-30 13:23:43
2011-06-30 13:23:43
我顶呀
FJCfjcFJCfjc
2011-06-30 14:11:12
2011-06-30 14:11:12
套接字发送字节流时是根据字节的多少进行多次发送的,所以接收时也要多次接收才行,不然可能有数据丢失问题.
huahua2000
2011-06-30 14:13:12
2011-06-30 14:13:12
把你的线程设置为后台线程,处理效率会更快!
hudingwen
2011-06-30 15:35:22
2011-06-30 15:35:22
套接字没丢包,是插缓存时可能由于线程安全问题,导致插包顺序问题,请看前几楼
hudingwen
2011-06-30 16:50:30
2011-06-30 16:50:30
大哥我需要解决问题的方法。。。
sp1234
2011-06-30 17:06:10
2011-06-30 17:06:10
你太逗了,这个怎么能“委托了另一个线程进行处理”呢?真是咄咄怪事。我是想不出来,除非你只是为了追时髦,或者你的整个接受代码都是抄别人的。
sp1234
2011-06-30 17:06:58
2011-06-30 17:06:58
这也太面向了吧?如果你在另一个线程中处理,你不承担责任吗?
ulihss
2011-06-30 17:10:23
2011-06-30 17:10:23
你包乱序是不是因为你的连接是不是断断续续的??
hudingwen
2011-07-01 01:35:23
2011-07-01 01:35:23
我不知道逗在哪?我也不是什么高手。如果你很高手就直接给出方法好了。
以下是我写的关socket的接收,委托部分,至于抄?微软官方有SocketAsyncEventArgs例子,一步一样自己看
而我帖子的第一段代码就是在InputHandler函数内
-
C# code
-
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); } } }
hudingwen
2011-07-01 01:40:07
2011-07-01 01:40:07
不是,长连接,局域网内,没断过,包乱序是我观察后得出的结果,不一定正确,但问了一些人,大多数都认为是因为BuffList的线程安全问题。因为我也不确定BeginInvoke(data, e, RecevieCallBack, Input)后是不是一定是单线程。如果不是的话,是否就有可能导致前面的还没写入,后面的先写入了,导致了包乱序。
hudingwen
2011-07-01 01:47:14
2011-07-01 01:47:14
我不太清楚你所说的承担责任,我理解是socket本身作为主线程时只需负责好握手,收,发这些基本就好,怎么处理收到的数据,和怎么组成数据发出去都应该由其他来处理,以达到最优化,或许是错的,或许是每个人的理解不一样吧
oONukeOo
2011-07-01 09:14:51
2011-07-01 09:14:51
你所看到的"掉包"现象实际上是异步调试出现的问题,实际上包的顺序是对的。。。
建议你仔细检查下GetData()函数,再组包的时候是否情况都考虑到了
建议你仔细检查下GetData()函数,再组包的时候是否情况都考虑到了
csnd_freeman
2011-07-01 10:58:14
2011-07-01 10:58:14
刚刚开始学习socket,来关注一下。
tyler3180
2011-07-01 16:35:50
2011-07-01 16:35:50
user.BuffList.InsertByteArray(data); //插入数据包缓冲池
加上互斥
类似生产者与消费者问题
hudingwen
2011-07-01 22:28:26
2011-07-01 22:28:26
确实是异步调用出现的问题,是类似多线程读写的问题,就是说insert数据时,有可能有多于一个异步调用,有可能刚好第二条线程先获取了锁先写了进去,如果不用这种异步调用而用阻塞调用,直接BeginReceive中处理是可以解决这个问题,但是这样无论是效率还是本身架构上都显得不合适。
hudingwen
2011-07-01 22:35:47
2011-07-01 22:35:47
你是指在使用 user.BuffList.InsertByteArray(data)时互斥?你说的我可以试试,但我觉得不一定行,因为异步调用Input函数时,Input函数本身是否只在一个线程上工作?如果不在是否会互斥?因为这个方式和我在Bufflist内函数加互斥似乎是一样的,我在BuffList.InsertByteArray(data)内部insert时已经加了锁,看代码
-
C# code
-
public void InsertByteArray( byte[] Data) { lock (locklist) { ByteList.AddRange(Data); } }
按道理来说,如果在需要执行BuffList.InsertByteArray(data)时加锁可以的话,那么当其执行InsertByteArray函数本身时就已经有互斥锁机制了。
hudingwen
2011-07-02 21:42:22
2011-07-02 21:42:22
有无高手呀~随便指点指点呀
oONukeOo
2011-07-03 23:57:12
2011-07-03 23:57:12
我们写过类似的代码。。。基本问题都出在处理上而不是想象中的线程问题(我们也是这么猜想的) 后来用了笨办法 在处理过程中添加写LOG 对照LOG测试处理中的问题 如果你还没解决这个问题 建议尝试下
alexccmm
2011-07-04 02:09:49
2011-07-04 02:09:49
可能原因、包发太快、n包同时到达
方案一:包与包之间暂停一下下:sleep时间自测罗
方案二:序列化后自己加上包长度、收到包后解出包长度、如果有多的就是下一个包、可就解出下一包、不可就等下一个数据、合包解包、
方案一比较简单
方案一:包与包之间暂停一下下:sleep时间自测罗
方案二:序列化后自己加上包长度、收到包后解出包长度、如果有多的就是下一个包、可就解出下一包、不可就等下一个数据、合包解包、
方案一比较简单
djc7811
2011-07-04 15:19:11
2011-07-04 15:19:11
交互模式收发
alexccmm
2011-07-04 15:27:57
2011-07-04 15:27:57
发包时断点、看序列化后的大小、
收包后、在断点、看收包后的大小、
看size有没有一样、
过大就是包挤在一块
收包后、在断点、看收包后的大小、
看size有没有一样、
过大就是包挤在一块
strife
2011-07-06 09:53:13
2011-07-06 09:53:13
看看看看
bei0305
2011-12-04 23:50:03
2011-12-04 23:50:03
兄弟你问题解决了吗?
chenandczh
2011-12-05 08:18:22
2011-12-05 08:18:22
1.Socket .Accept
判断Socket.Connect
true就接收,结束后到1
false就循环到1
判断Socket.Connect
true就接收,结束后到1
false就循环到1