using System; using XGame.Framework.Interfaces; namespace XGame.Framework.Network { internal class MsgSender : IMsgSender, IReset { private ISessionContext _context; private int seqID = -1; /// /// 消息间隔,默认3秒 /// private const int _interval = 3000; private long _lastTime = 0; private int _lastID = -1; public MsgSender(ISessionContext context) { _context = context; } public bool IsCanSend(IMessage message, bool useFilter) { if (useFilter) { var nowTime = _context.Time.GetNowTime(); if (_lastTime == 0 || nowTime - _lastTime > _interval) { // 没记录时间 或 已经超时, 刷新时间 _lastTime = nowTime; } else { return false; } } message.InstanceID = ++seqID; if (useFilter) { _lastID = message.InstanceID; } return true; } //|<- 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 | | public ESessionCode Send(IMessage message, bool openEncrypt) { _context.Serializer.Write(message, out var bytes, out var msgOffset, out var msgLength); //magic bytes[0] = NetDefine.MAGIC; //type compress int type = (int)MsgType.REQUEST << 6; bool isCompress = (msgLength + NetDefine.HEAD_LENGTH_REQUEST) > NetDefine.CompressThreshold; int compress = (isCompress ? 1 : 0) << 5; int encryption = (openEncrypt ? 1 : 0) << 4; bytes[1] = Convert.ToByte((compress + type + encryption) & 0xFF); //seqID bytes[2] = Convert.ToByte(message.InstanceID >> 24 & 0xFF); bytes[3] = Convert.ToByte(message.InstanceID >> 16 & 0xFF); bytes[4] = Convert.ToByte(message.InstanceID >> 8 & 0xFF); bytes[5] = Convert.ToByte(message.InstanceID & 0xFF); //protoID bytes[6] = Convert.ToByte(message.ProtocolID >> 24 & 0xFF); bytes[7] = Convert.ToByte(message.ProtocolID >> 16 & 0xFF); bytes[8] = Convert.ToByte(message.ProtocolID >> 8 & 0xFF); bytes[9] = Convert.ToByte(message.ProtocolID & 0xFF); if (isCompress) { _context.Compressor.Compress(ref bytes, ref msgOffset, ref msgLength); } if (openEncrypt)//rc4的话 用新数组进行保存 { _context.Encryptor.Encrypt(ref bytes, ref msgOffset, ref msgLength); } //msglengh bytes[10] = Convert.ToByte(msgLength >> 8 & 0xFF); bytes[11] = Convert.ToByte(msgLength & 0xFF); NetLog.LogHexString($"发送消息", bytes, 0, msgLength + NetDefine.HEAD_LENGTH_REQUEST); var result = _context.Session.Send(bytes, 0, msgLength + NetDefine.HEAD_LENGTH_REQUEST); return result ? ESessionCode.None : ESessionCode.SendFailed; } public void Reset() { seqID = -1; _lastID = -1; _lastTime = 0; } public bool VerifyInstanceID(int instanceID) { if (_lastID == instanceID) { _lastTime = 0; return true; } return false; } //private bool CanSendMsg(IMessage msg) //{ // if (!_sessionNode.MsgContext.CanSend)//false request 和 response 没有对应 // { // Log.Debug(string.Format("[Session Send Filter] <{0}> {1} lastSeq: {2} \n消息发送过快,上条消息尚未回复导致消息被过滤,请重发或使用INetModule.Send(string sessionType, IMessage msg, bool isFilter),isFilter设置为false\n{3}", msg.ProtocolID, msg.GetType().Name, _sessionNode.MsgContext.LastID, XJson.ToJson(msg))); // var args = ObjectPool.Acquire(); // args.Message = msg; // _sessionNode.Notify(EventDefine.SESSION_MSG_FILTER, args); // ObjectPool.Recycle(args); // return false; // } // _sessionNode.MsgContext.CanSend = false; // //计时开始 // _timer?.Cancel(); // _timer = _timeModule.AddDelayTimer(_interval, Timeout); // return true; //} //private void DebugMessage(IMessage message) //{ // if (_sessionNode.bDebug) // { // Log.Info("[Session] Send <{1}> {2}: Seq:{4} Timestamp:{0}\n{3}", // _timeModule.GetNowTime(ClockType.Client), message.ProtocolID, message.GetType().Name, XJson.ToJson(message), message.InstanceID); // } //} //private void SendFail(IMessage message) //{ // var args = ObjectPool.Acquire(); // args.message = message; // if (_sessionNode.bDebug) // { // Log.Error("[Session Send Fail] Send <{1}> {2}: Timestamp:{0}\n{3}", // _timeModule.GetNowTime(ClockType.Client), message.ProtocolID, message.GetType().Name, XJson.ToJson(message)); // } // _sessionNode.Notify(EventDefine.SESSION_CANT_SEND, args); // ObjectPool.Recycle(args); //} //private void SendEvent(IMessage msg, bool isFilter) //{ // var args = ObjectPool.Acquire(); // args.protocolID = msg.ProtocolID; // args.context = msg.Context; // args.IsFilter = isFilter; // args.RequestMsg = msg; // args.seq = msg.InstanceID; // _sessionNode.Notify(EventDefine.SESSION_REQUEST_SENT, args); // ObjectPool.Recycle(args); //} } }