internal override void Dispatch(Service service, Service.ProtocolFactoryHandle factoryHandle) { if (IsRequest) { service.DispatchProtocol(this, factoryHandle); return; } // response, 从上下文中查找原来发送的rpc对象,并派发该对象。 Rpc <TArgument, TResult> context = service.RemoveRpcContext <Rpc <TArgument, TResult> >(SessionId); if (null == context) { logger.Info("rpc response: lost context, maybe timeout. {0}", this); return; } context.IsRequest = false; context.Result = Result; context.Sender = Sender; context.ResultCode = ResultCode; context.UserState = UserState; if (context.Future != null) { context.Future.SetResult(context.Result); return; // SendForWait,设置结果唤醒等待者。 } context.IsTimeout = false; // not need if (null != context.ResponseHandle) { service.DispatchRpcResponse(context, context.ResponseHandle, factoryHandle); } }
internal virtual void Dispatch(Service service, Service.ProtocolFactoryHandle factoryHandle) { service.DispatchProtocol(this, factoryHandle); }
/// <summary> /// Id + size + protocol.bytes /// </summary> /// <param name="bb"></param> /// <returns></returns> internal static void Decode(Service service, AsyncSocket so, ByteBuffer bb, Zeze.Services.ToLuaService.ToLua toLua = null) { ByteBuffer os = ByteBuffer.Wrap(bb.Bytes, bb.ReadIndex, bb.Size); // 创建一个新的ByteBuffer,解码确认了才修改bb索引。 while (os.Size > 0) { // 尝试读取协议类型和大小 int type; int size; int readIndexSaved = os.ReadIndex; if (os.Size >= 8) // protocl header size. { type = os.ReadInt4(); size = os.ReadInt4(); } else { // SKIP! 只有协议发送被分成很小的包,协议头都不够的时候才会发生这个异常。几乎不可能发生。 //bb.ReadIndex = readIndexSaved; return; } // 以前写过的实现在数据不够之前会根据type检查size是否太大。 // 现在去掉协议的最大大小的配置了.由总的参数 SocketOptions.InputBufferMaxProtocolSize 限制。 // 参考 AsyncSocket if (size < 0 || size > os.Size) { // 数据不够时检查。这个检测不需要严格的。如果数据够,那就优先处理。 if (size < 0 || size > service.SocketOptions.InputBufferMaxProtocolSize) { var pName = service.FindProtocolFactoryHandle(type)?.Factory().GetType().FullName; throw new Exception($"Decode InputBufferMaxProtocolSize '{service.Name}' p='{pName}' type={type} size={size}"); } // not enough data. try next time. bb.ReadIndex = readIndexSaved; return; } // 直接使用os,可以少创建对象,否则 Wrap 一个更安全: // ByteBuffer.Wrap(os.Bytes, os.ReadIndex, size) // 使用Wrap的话,记得手动增加: os.ReadIndex += size; Service.ProtocolFactoryHandle factoryHandle = service.FindProtocolFactoryHandle(type); if (null != factoryHandle) { Protocol p = factoryHandle.Factory(); p.Service = service; p.Decode(os); p.Sender = so; p.UserState = so.UserState; p.Dispatch(service, factoryHandle); continue; } // 优先派发c#实现,然后尝试lua实现,最后UnknownProtocol。 if (null != toLua) { if (toLua.DecodeAndDispatch(service, so.SessionId, type, os)) { continue; } } service.DispatchUnknownProtocol(so, type, ByteBuffer.Wrap(os.Bytes, os.ReadIndex, size)); os.ReadIndex += size; } bb.ReadIndex = os.ReadIndex; }