之前客户端在网络条件好的时候,运行没问题.但是有时候手机的网络不稳定,接受数据可能不稳定,导致接受数据错误,一直都不知道,原来是接受数据处理的不够好!

现在更改过后的接受数据的逻辑如下:

    //接收
public void Receive(int length, bool tag, byte[] head)
{
if (clientSocket != null && clientSocket.Connected)
{
StateObject stateObject = new StateObject(length, clientSocket, tag, head);
clientSocket.BeginReceive(stateObject.sBuffer, , stateObject.sBuffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), stateObject);
}
} //接收回调
private void receiveCallback(IAsyncResult asyncReceive)
{
try
{
//异步接收的结果
StateObject stateObject = (StateObject)asyncReceive.AsyncState; if (stateObject.sSocket == null)
{
m_CallReceive(false, Error_Socket.SOCKET_NULL, "", null, "");
return;
}
else if (!stateObject.sSocket.Connected)
{
m_CallReceive(false, Error_Socket.SOCKET_UNCONNECT, "", null, "");
Debug.Log("连接断开");
return;
}
//接收标示
if (stateObject.spkgTag)
{
#region This_TIME_RECV_PKG_HEAD
int recv_this_time_length = stateObject.sSocket.EndReceive(asyncReceive);
//接收到的数据
byte[] m_recv_Buffer = new byte[recv_this_time_length];
ComClass.MemCpy(m_recv_Buffer, stateObject.sBuffer, , recv_this_time_length); mypkg_head pkg_head_tmp = new mypkg_head();
pkg_head_tmp.unpacket(m_recv_Buffer);//解析数据包 //接收消息长度为10
if (pkg_head_tmp.length == && recv_this_time_length>=)
{
m_CallReceive(true, error_Socket, "", m_recv_Buffer, "");
}
else if(pkg_head_tmp.length> && recv_this_time_length>=)
{
Receive(pkg_head_tmp.length - recv_this_time_length, false, m_recv_Buffer);
return;
}else{
Debug.LogError("######## ERROR PKG_HEAD ERROR [ "+recv_this_time_length+" bytes] #############");
}
#endregion }
else//数据
{
#region THIS_TIME_CONTINUE_RECV_DATA
int have_recv_length=stateObject.sheadBuffer.Length;
int recv_this_time_length = stateObject.sSocket.EndReceive(asyncReceive);
//接收到的数据
byte[] m_recv_Buffer = new byte[recv_this_time_length + have_recv_length];
//////m_recv_Buffer = ComClass.ConnectBytes(stateObject.sheadBuffer, stateObject.sBuffer);
ComClass.MemCpy(m_recv_Buffer, stateObject.sheadBuffer, , stateObject.sheadBuffer.Length);
ComClass.MemCpy(m_recv_Buffer, stateObject.sBuffer, stateObject.sheadBuffer.Length, recv_this_time_length); mypkg_head pkg_head_tmp = new mypkg_head();
pkg_head_tmp.unpacket(m_recv_Buffer);//解析数据包 Debug.Log("[length="+pkg_head_tmp.length+"][type="+pkg_head_tmp.type+"][command="+pkg_head_tmp.command+"][uid="+pkg_head_tmp.uid+
"] 前面已经接受了"+have_recv_length+"个字节;本次接受"+recv_this_time_length+"个字节; 已经累计接受了"+m_recv_Buffer.Length+"个字节");
//sbuffer分配的大小 比实际接受到的小,那么就得继续接受完!!!
//##if(stateObject.sBuffer.Length!=recv_this_time_length && false){
//## Debug.LogError("#################### ERROR:stateObject.sBuffer.Length["+stateObject.sBuffer.Length+
//## "]!=recv_this_time_length["+recv_this_time_length+"] ####################");
//## return;
//##} if(m_recv_Buffer.Length < pkg_head_tmp.length){
Debug.Log("## TOBE Continue:还需要接受"+(pkg_head_tmp.length-m_recv_Buffer.Length)+"个字节 ");
Receive(pkg_head_tmp.length - m_recv_Buffer.Length, false, m_recv_Buffer);
return ;
}else if(m_recv_Buffer.Length == pkg_head_tmp.length){
Debug.Log("## 刚刚好接受完一个包数据,进行处理...[pkg_head_tmp.length="+pkg_head_tmp.length+"]");
m_CallReceive(true, error_Socket, "", m_recv_Buffer, "");
}else{
Debug.LogError("========ERROR=================");
Debug.LogError(" 多接受了"+(pkg_head_tmp.length-m_recv_Buffer.Length)+"个字节!!!!!!! ");
Debug.LogError("========ERROR=================");
return;
}
#endregion
}
//结束异步的数据读取之后,从新开始接收数据
Receive(, true, null);
}
catch (System.Exception ex)
{
if (null != m_CallReceive)
{
m_CallReceive(false, Error_Socket.RECEIV_UNSUCCESS_UNKNOW, ex.ToString(), null, "");
Debug.Log(ex.ToString());
}
}
} //定义Object
private class StateObject
{
internal byte[] sBuffer;//本次接收到的实际数据
internal Socket sSocket;//socket
internal bool spkgTag;//包的标示
internal byte[] sheadBuffer;//消息头的数据
internal StateObject(int size, Socket sock, bool tag, byte[] data)
{
sheadBuffer = data;
sBuffer = new byte[size];
sSocket = sock;
spkgTag = tag;
}
}

最主要的还是 如果数据不够的话,要继续接受。以上代码 是公司框架之后的代码,是游戏代码的一部分,只供学习逻辑,不可以直接运行!

这是我自己的逻辑。

其实还有另外一种逻辑,那就是 使劲接受到一个比较大的缓冲区。接受的足够了,在处理,其他的继续接受。

【手机网络游戏 编程】C#异步socketAPI调用 处理数据的流程的更多相关文章

  1. 【憩园】C#并发编程之异步编程(一)

    写在前面 C#5.0中,对异步编程进行了一次革命性的重构,引入了async和await这两个关键字,使得开发人员在不需要深刻了解异步编程的底层原理,就可以写出十分优美而又代码量极少的代码.如果使用得当 ...

  2. Java网络编程中异步编程的理解

    目录 前言 一.异步,同步,阻塞和非阻塞的理解 二.异步编程从用户层面和框架层面不同角度的理解 用户角度的理解 框架角度的理解 三.为什么使用异步 四.理解这些能在实际中的应用 六.困惑 参考文章 前 ...

  3. C#复习笔记(5)--C#5:简化的异步编程(异步编程的基础知识)

    异步编程的基础知识 C#5推出的async和await关键字使异步编程从表面上来说变得简单了许多,我们只需要了解不多的知识就可以编写出有效的异步代码. 在介绍async和await之前,先介绍一些基础 ...

  4. Windows系统编程之异步I/O和完成端口

    Windows系统编程之异步I/O和完成端口[作者]北极星2003[来源]看雪技术论坛(bbs.pediy.com) [时间]2006年7月1日 一.  同步I/O和异步I/O 在介绍这部分内容之前先 ...

  5. .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)

    本文内容 异步编程类型 异步编程模型(APM) 参考资料 首先澄清,异步编程模式(Asynchronous Programming Patterns)与异步编程模型(Asynchronous Prog ...

  6. C#并发编程之异步编程2

    C#并发编程之异步编程(二)   写在前面 前面一篇文章介绍了异步编程的基本内容,同时也简要说明了async和await的一些用法.本篇文章将对async和await这两个关键字进行深入探讨,研究其中 ...

  7. 从执行上下文角度重新理解.NET(Core)的多线程编程[1]:基于调用链的”参数”传递

    线程是操作系统能够进行运算调度的最小单位,操作系统线程进一步被封装成托管的Thread对象,手工创建并管理Thread对象已经成为了所能做到的对线程最细粒度的控制了.后来我们有了ThreadPool, ...

  8. 进程内部异步事件调用组件Async-Event

    项目坐标:https://github.com/cncduLee/async-event async-event 进程内部异步事件调用组件 解决什么问题: 加速服务处理效率.提供进程级别的事件发布和异 ...

  9. Matlab.NET混合编程技巧之——直接调用Matlab内置函数(附源码)

    原文:[原创]Matlab.NET混合编程技巧之--直接调用Matlab内置函数(附源码) 在我的上一篇文章[原创]Matlab.NET混编技巧之——找出Matlab内置函数中,已经大概的介绍了mat ...

随机推荐

  1. Cookie安全漫谈(转)

    add by zhj: 我也同意作者的观点,JavaScript 操作 Cookie 是一种不正常的做法:可以用 JavaScript 操作 Cookie 完成的功能,一样可以在服务端来完成. js操 ...

  2. 023.Zabbix自定义(邮箱)脚本告警-02

    待补充 有需要,请留言!

  3. 002.etcd使用场景

    引用链接: https://blog.csdn.net/linuxheik/article/details/77853119 https://www.cnblogs.com/doscho/p/6221 ...

  4. JAVA 图形开发之计算器设计(事件监听机制)

    /*文章中用到的代码只是一部分,需要源码的可通过邮箱联系我 1978702969@qq.com*/ 前段时间刚帮同学用MFC写了个计算器,现在学到JAVA的图形开发,就试着水了一个计算器出来.(可以说 ...

  5. oracle 编码

    select * from nls_database_parameters where parameter ='NLS_CHARACTERSET'; PARAMETER VALUE --------- ...

  6. SOAP port

    To determine the SOAP port on WebSphere Base: Server Types > WebSphere application servers > [ ...

  7. mongodb spring 配置文件

    在使用spring-data-mongodb中,需要配置spring文件,如下: mongodb.xml <?xml version="1.0" encoding=" ...

  8. Java 操纵XML之修改XML文件

    Java 操纵XML之修改XML文件 一.JAVA DOM PARSER DOM interfaces The DOM defines several Java interfaces. Here ar ...

  9. BZOJ.1028.[JSOI2007]麻将(贪心)

    题目链接 枚举对子,枚举每张牌,先出完它的刻子,剩下的出顺子.\(O(n^3)\). 不是这样 -> 出完所有刻子,最后出顺子.(日常zz) 优先仨相同的,然后顺子,有一次且一定要用一次机会补顺 ...

  10. 喵哈哈村的魔法考试 Round #6 (Div.3) 题解

    有任何问题 直接联系QQ:475517977 喵哈哈村的代码传说 第一章 冒泡排序 第一题就是排序嘛,在ACM/OI竞赛中,我只推崇一种排序方法,就是直接调用algorithm里面的sort函数. # ...