using System; namespace XGame.Framework.Network { internal class MsgReceiver : IMsgReceiver { private IMsgReceiverListener _listener; private ISessionContext _context; public MsgReceiver(IMsgReceiverListener listener, ISessionContext context) { _listener = listener; _context = context; } //response 12 //|<- Head ->|<- Body ->| //| magic | type | compress | encryption |0000| seqID | protoId| msglength| msg | //| 1byte | 2bit | 1bit | 1bit |4bit| 4byte | 4byte | 2byte | Nbyte | //| 0 | 1 | 2 3 4 5 | 6789 | 10 11 | | //push 8 //|<- Head ->|<- Body ->| //| magic | type | compress | encryption |0000| protoId| msglength| msg | //| 1byte | 2bit | 1bit | 1bit |4bit| 4byte | 2byte | Nbyte | //| 0 | 1 | 2345 | 6 7 | | public void Receive(byte[] bytes, int headLen, int msgLen) { int type = bytes[1] >> 6; int compress = bytes[1] >> 5 & 0x1; int encryption = bytes[1] >> 4 & 0x1; int protoID = -1; int seqID = -1; NetLog.LogHexString($"[Net] headLen:{headLen} msgLen:{msgLen}\n解析前:", bytes, headLen, msgLen); if (bytes[0] != NetDefine.MAGIC) { Log.Error($"[Net] 协议版本错误. bytes:{bytes[0]} magic:{NetDefine.MAGIC}"); return; } if (type != (int)MsgType.REQUEST) { //收到任何消息都算收到心跳应答 _listener?.OnHeartbeatReceived(); } switch ((MsgType)type) { case MsgType.HEART_BEAT: NetLog.LogVerbose("[Net] 收到心跳应答消息."); return; case MsgType.RESPONSE: seqID = (bytes[2] << 24) + (bytes[3] << 16) + (bytes[4] << 8) + (bytes[5]); protoID = (bytes[6] << 24) + (bytes[7] << 16) + (bytes[8] << 8) + (bytes[9]); NetLog.LogVerbose($"[Net] [Response] protoid:{protoID} seqID:{seqID}"); if (seqID <= -1) { Log.Error(string.Format("[Net] seq:{0} HeadLen:{1} MsgLen:{2} 抛弃一条非客户端请求,服务端私自发送来的消息", seqID, headLen, msgLen)); return; } break; case MsgType.PUSH: protoID = (bytes[2] << 24) + (bytes[3] << 16) + (bytes[4] << 8) + (bytes[5]); NetLog.LogVerbose($"[Net] [Push] protoid:{protoID}"); break; default: Log.Error($"[Net] MsgType未知的一条消息 type:{type}"); return; } //做解密 if (encryption == 1) { try { _context.Encryptor.Decrypt(ref bytes, ref headLen, ref msgLen); NetLog.LogHexString($"[Net] type:{(MsgType)type} protoid:{protoID} seq:{seqID}\n<<<<<解密后>>>>>:", bytes, headLen, msgLen); } catch (Exception e) { Log.Exception($"[Net] 解密 msg {protoID} 出错\n", e); return; } } //做解压 if (compress == 1) { try { _context.Compressor.Decompress(ref bytes, ref headLen, ref msgLen);//新的buffer NetLog.LogHexString($"[Net] type:{(MsgType)type} protoid:{protoID} seq:{seqID}\n■■■■■解压后■■■■■:", bytes, headLen, msgLen); } catch (Exception e) { Log.Exception($"[Net] 解压 msg {protoID} 出错\n", e); return; } } IMessage msg = null;// = _context.Generator.GetMessage(protoID); if (msgLen != 0) { _context.Serializer.Read(bytes, headLen, msgLen + headLen, protoID, out msg); } if (msg != null) { //if (msgLen != 0) //{ // try // { // msg.ParseFrom(bytes, headLen, msgLen + headLen); // NetLog.LogVerbose($"[MsgReceiver] type:{(MsgType)type} protoid:{protoID} seq:{seqID}\n解析后:[{msg.GetType().Name}]{XJson.ToJson(msg)}"); // } // catch (Exception e) // { // Log.Exception($"[Session] 解析 msg {protoID} Excep出错 可能是双端proto文件没有同步 还有可能是本服跨服proto不一致\n", e); // return; // } //} msg.InstanceID = seqID; if (msg.ProtocolID == NetDefine.CONN_PROTO_ID && msg.InstanceID == NetDefine.CONN_SEQ_ID) { NetLog.LogVerbose($"[Net] type:{(MsgType)type} protoid:{protoID} seq:{seqID} process immediately!!!"); _context.Processer.Process(msg);//对握手这条立即处理。 } else { //var data = SessionThreadData.Acquire(); //data.EventType = type == (int)MsgType.PUSH ? ESessionCode.ProcessPush : ESessionCode.ProcessResponse; //data.Context = msg; NetLog.LogVerbose($"[Net] type:{(MsgType)type} protoid:{protoID} seq:{seqID} Enqueue wait to process"); _context.Synchronizer.Enqueue(msg); } } else { Log.Error($"[Net] protoid : {protoID} 取不到IMessage,可能是proto文件没有生成"); } } } }