博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【手机网络游戏 编程】C#异步socketAPI调用 处理数据的流程
阅读量:5943 次
发布时间:2019-06-19

本文共 5493 字,大约阅读时间需要 18 分钟。

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

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

//接收    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, 0, 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, 0, 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 == 10 && recv_this_time_length>=10)                {                    m_CallReceive(true, error_Socket, "", m_recv_Buffer, "");                }                else if(pkg_head_tmp.length>10 && recv_this_time_length>=10)                {                    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, 0, 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(10, 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;        }    }

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

 

这是我自己的逻辑。

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

 

转载地址:http://sggtx.baihongyu.com/

你可能感兴趣的文章
layer弹出信息框API
查看>>
delete from inner join
查看>>
WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍...
查看>>
git merge 和 git merge --no-ff
查看>>
独立软件开发商进军SaaS注意八个问题,互联网营销
查看>>
jdk内存的分配
查看>>
关于self.用法的一些总结
查看>>
UIView翻译 (参考)
查看>>
Android Display buffer_handle_t的定义
查看>>
SSH详解
查看>>
ASM概述
查看>>
【290】Python 函数
查看>>
godaddy域名转发(域名跳转)设置教程
查看>>
silverlight学习布局之:布局stackpanel
查看>>
理解并自定义HttpHandler
查看>>
从前后端分离到GraphQL,携程如何用Node实现?\n
查看>>
JavaScript标准库系列——RegExp对象(三)
查看>>
Linux Namespace系列(09):利用Namespace创建一个简单可用的容器
查看>>
关于缓存命中率的几个关键问题!
查看>>
oracle中create table with as和insert into with as语句
查看>>