/// <summary> /// Initialize net component and connect to remote server. /// </summary> /// <param name="remoteAddress">The address of remote server to connect.</param> /// <param name="remotePort">The port of remote server to connect.</param> public Boolean Initialize(String remoteAddress, Int32 remotePort) { // 客户端处理IPV6的时候逻辑,需要用到 #if UNITY_5_3_OR_NEWER if (Application.platform == RuntimePlatform.IPhonePlayer) { String newServerIp = ""; AddressFamily newAddressFamily = AddressFamily.InterNetwork; getIPType(remoteAddress, remotePort.ToString(), out newServerIp, out newAddressFamily); if (!string.IsNullOrEmpty(newServerIp)) { remoteAddress = newServerIp; } } #endif // analyze the ip address and port info IPAddress myIp; if (IPAddress.TryParse(remoteAddress, out myIp)) { //strMsg = String.Format("BuildPeer TryParse {0} success", remoteAddress); //Debug.WriteLine(strMsg); m_ipEndPoint = new IPEndPoint(myIp, remotePort); } else { //strMsg = String.Format("BuildPeer GetHostEntry {0} fail", remoteAddress); //Debug.WriteLine(strMsg); return(false); } // Do some cleanup if necessery if (State != ConnectionState.None) { Close(); } // Clean all messages of last connection RecvQueue.Clear(); // Clean all event args of last connection m_connEventArg = new SocketAsyncEventArgs(); m_receiveEventArg = new SocketAsyncEventArgs(); // init event args m_connEventArg.Completed += new EventHandler <SocketAsyncEventArgs>(OnCompletedForConnect); m_connEventArg.RemoteEndPoint = m_ipEndPoint; m_receiveEventArg.Completed += new EventHandler <SocketAsyncEventArgs>(OnCompletedForReceive); m_receiveEventArg.SetBuffer(new byte[ProtoConst.MAX_PACKAGE_LENGTH], 0, ProtoConst.MAX_PACKAGE_LENGTH); // Change state State = ConnectionState.Connecting; // Create work resource RecvCache = new MessageBlock((int)ConnectionConst.CACHE_MAX_BYTE); try { StartConnectionWork(); }catch (Exception e) { Log.Error(e); return(true); } return(true); }
/// <summary> /// Decodes the message. /// </summary> /// <returns>The message.</returns> /// <param name="dataBlock">Data block.</param> /// <param name="dataOffset">Data offset.</param> /// <param name="dataLen">Data length.</param> /// <param name="newMsg">New message.</param> /// <returns> /// != null : A protocol message /// == null : No full message exist /// Exception : ProtoException to indicate HACK stream /// </returns> public static Object DecodeMessage(MessageBlock rCache, out ushort msgId, out bool isRpc) { msgId = 0; isRpc = false; // get the message head's length int headLength = sizeof(ushort) * 2; // Not enough data for header if (rCache.Length < headLength) { //Debug.WriteLine(String.Format("DecodeMessage Not enough data for header. rCache.Length={0} < headLength={1}", rCache.Length, headLength)); return(null); } // get message length ushort pakFullLength = rCache.ReadUInt16(); // Bad stream if (pakFullLength < headLength) { throw new ProtoException(string.Format("Hack stream, TotalLength={0}", pakFullLength)); } int pakBodyLength = pakFullLength - headLength; //Debug.WriteLine(String.Format("DecodeMessage Before rCache.Length={0} pakBodyLength={1} ", rCache.Length, pakBodyLength)); // Not enough data for body // 注意这里需要考虑后面一个包头的长度 if (rCache.Length < pakBodyLength + sizeof(ushort)) { // Move read ptr to back // 此处只处理了UInt16长度的数据,所以回滚需要一致,不能使用headLength rCache.ReadPtr(-(sizeof(ushort))); //Debug.WriteLine(String.Format("DecodeMessage Not enough data for body rCache.Length={0} < pakBodyLength={1}", rCache.Length, pakBodyLength)); return(null); } // get message id field ushort pakMessageIdField = rCache.ReadUInt16(); // get compressed tag isRpc = pakMessageIdField >> (sizeof(ushort) * 8 - 1) == 1; // get the protocol id msgId = (ushort)(pakMessageIdField & 0x7FFF); // deserialize message, we should decompress message body data if needed Type pakType = OpcodeTypeDictionary.Instance.GetTypeById(msgId); // Use ProtoBuf to deserialize message //object ccMsg = MessageFactory.CreateMessage(pakType);//2019.7.17改为对象池 object ccMsg = Activator.CreateInstance(pakType); //Debug.WriteLine(String.Format("DecodeMessage msgId={0} pakBodyLength={1} isCompressed={2} pakType={3}", msgId, pakBodyLength, isCompressed, pakType.ToString())); try { using (MemoryStream readStream = rCache.GetStream(pakBodyLength)) { //将消息序列化,根据所提供的序列化器进行序列化和反序列化 ProtobufPraserHelper.s_protobufPacker.DeserializeFrom(ccMsg, readStream); } } catch (Exception ex) { throw new Exception(string.Format("msgId={0}, isRpc={1} pakBodyLength={2}", msgId, isRpc, pakBodyLength), ex); } //Debug.WriteLine(String.Format("DecodeMessage rCacheInfo Length={0} WrPtr={1} RdPtr={2}", rCache.Length, rCache.WrPtr, rCache.RdPtr)); return(ccMsg); }