之前客户端在网络条件好的时候,运行没问题.但是有时候手机的网络不稳定,接受数据可能不稳定,导致接受数据错误,一直都不知道,原来是接受数据处理的不够好!
现在更改过后的接受数据的逻辑如下:
//接收 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; } }
最主要的还是 如果数据不够的话,要继续接受。以上代码 是公司框架之后的代码,是游戏代码的一部分,只供学习逻辑,不可以直接运行!
这是我自己的逻辑。
其实还有另外一种逻辑,那就是 使劲接受到一个比较大的缓冲区。接受的足够了,在处理,其他的继续接受。