异步接收数据,第一次接收到不解析,第二次直接从上次的地方进行解析?

yuanyuanluoluo 2019-03-24 03:49:58
最近在把同步改成异步通信,遇到一个奇怪的地方,接到数据后不直接解析,卡住不走了,然后第二次从卡住的地方直接运行解析数据,就是卡在这里:iBytesHead = ThisClient.Receive(recvBytes1, recvBytes1.Length, 0);
个人觉得这接收是不是还是同步接收,但是自己刚接触异步通信,想改却不知道怎么改,特来求助大佬,第一次输出2就不走了,第二次接到数据,直接输出3,然后往下运行了,奇数次就卡在2这,偶数次就直接从卡住的地方运行了,

public void recmessage(byte[] data)
{
if (ThisClient.Connected)
{

//接受消息头(消息校验码4字节 + 消息长度4字节 + 身份ID8字节 + 主命令4字节 + 子命令4字节 + 加密方式4字节 = 28字节)
int HeadLength = 28;
//存储消息头的所有字节数
byte[] recvBytesHead = new byte[HeadLength];
//如果当前需要接收的字节数大于0,则循环接收
while (HeadLength > 0)
{
byte[] recvBytes1 = new byte[28];
//将本次传输已经接收到的字节数置0
int iBytesHead = 0;
//如果当前需要接收的字节数大于缓存区大小,则按缓存区大小进行接收,相反则按剩余需要接收的字节数进行接收
if (HeadLength >= recvBytes1.Length)
{
log.text += "2";
iBytesHead = ThisClient.Receive(recvBytes1, recvBytes1.Length, 0);
log.text += "3";
}
else
{
iBytesHead = ThisClient.Receive(recvBytes1, HeadLength, 0);

}
//将接收到的字节数保存
recvBytes1.CopyTo(recvBytesHead, recvBytesHead.Length - HeadLength);
//减去已经接收到的字节数
HeadLength -= iBytesHead;
}
//接收消息体(消息体的长度存储在消息头的4至8索引位置的字节里)
byte[] bytes = new byte[4];
Array.Copy(recvBytesHead, 4, bytes, 0, 4);
int BodyLength = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(bytes, 0));
//存储消息体的所有字节数
byte[] recvBytesBody = new byte[BodyLength];
//如果当前需要接收的字节数大于0,则循环接收
while (BodyLength > 0)
{
byte[] recvBytes2 = new byte[BodyLength < 1024 ? BodyLength : 1024];
//将本次传输已经接收到的字节数置0
int iBytesBody = 0;
//如果当前需要接收的字节数大于缓存区大小,则按缓存区大小进行接收,相反则按剩余需要接收的字节数进行接收
if (BodyLength >= recvBytes2.Length)
{
iBytesBody = ThisClient.Receive(recvBytes2, recvBytes2.Length, 0);
}
else
{
iBytesBody = ThisClient.Receive(recvBytes2, BodyLength, 0);
}
//将接收到的字节数保存
recvBytes2.CopyTo(recvBytesBody, recvBytesBody.Length - BodyLength);
//减去已经接收到的字节数
BodyLength -= iBytesBody;
}
string res = DataPackagesTransform.UnpackDataToStr(recvBytesHead, recvBytesBody);
RecMsg.Enqueue(res);
log.text += "队列加入元素";
}
}
...全文
695 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
yuanyuanluoluo 2019-03-26
  • 打赏
  • 举报
回复
好的,这个通信刚刚接触,也看了一些范例,还是有错误,感觉整个流程好像还不完善,我去看看
  • 打赏
  • 举报
回复
引用 4 楼 yuanyuanluoluo 的回复:
那应该有什么思路
可以找本教程学软件设计、学会画事件和异步流程图、类型关联图、状态图/甬道图等等知识。而不是只见个别语句。
wanghui0380 2019-03-26
  • 打赏
  • 举报
回复
看来最近那一波面试题“求循环次数”“求单调区间”-------还真是能难倒一大批程序员。

还是一摸一样的问题。

这样吧,楼主有空的时候的研究一下“dotnetty”,如果没空也直接换成“dotnetty”把。(他已经实现,你拿来直接用就好。)当然建议是如果有空还是看看人家写的东西。(我已经不想在说状态机,管道,流式数据处理了,半个月说了好多遍了,有点郁闷了)
xian_wwq 2019-03-26
  • 打赏
  • 举报
回复
数据接收和数据解析分离,
数据接收后,直接放入线程安全队列(容器),防止解析耗时导致接收超时
数据解析建议使用线程池或者任务池,提高效率
yuanyuanluoluo 2019-03-26
  • 打赏
  • 举报
回复
那应该有什么思路
  • 打赏
  • 举报
回复
异步,就不能满脑子只有“死循环+阻塞”思路。
yuanyuanluoluo 2019-03-24
  • 打赏
  • 举报
回复
#region 数据接收
private void AsyncRecive()
{
if (ThisClient.Connected)
{
ThisClient.BeginReceive(_recvBytes, 0, _recvBytes.Length, SocketFlags.None, CallbackRecive, ThisClient);
}
}
private void CallbackRecive(IAsyncResult ar)
{
try
{
int lenth = ThisClient.EndReceive(ar);
if (lenth > 0)
{
RecvByte(_recvBytes, lenth);
log.text += string.Format("<color=yellow>_recvBytes的长度是:{0}</color>", lenth);
recmessage(_recvBuffer._allRecvBytes);
}
}
catch (Exception)
{
}
AsyncRecive();
}
#endregion
这里是异步接收消息,接收后解析消息,消息分为消息头和消息体
无情时尚 2019-03-24
  • 打赏
  • 举报
回复
没有看出来,那里是异步接收

110,533

社区成员

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

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

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