页首Html代码

返回顶部

【手机网络游戏 编程】C#异步socketAPI调用 处理数据的流程

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

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

    //接收
    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;
        }
    }

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

 

这是我自己的逻辑。

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

 

posted @ 2014-05-14 11:56  ayanmw  阅读(683)  评论(0编辑  收藏  举报

页脚Html代码