private async static void RpcDo(AChannel channel, Opcode opcode, byte[] messageBytes) { byte[] opcodeBuffer; int id = BitConverter.ToInt32(messageBytes, 2); byte[] idBuffer = BitConverter.GetBytes(id); try { opcodeBuffer = BitConverter.GetBytes((ushort)Opcode.RpcResponse); byte[] result = await World.Instance.GetComponent <MessageComponent>().RunAsync(opcode, messageBytes); channel.SendAsync(new List <byte[]> { opcodeBuffer, idBuffer, result }); } catch (Exception e) { opcodeBuffer = BitConverter.GetBytes((ushort)Opcode.RpcException); BinaryFormatter formatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.All)); using (MemoryStream stream = new MemoryStream()) { formatter.Serialize(stream, e); channel.SendAsync(new List <byte[]> { opcodeBuffer, idBuffer, stream.ToArray() }); } } }
/// <summary> /// Rpc请求 /// </summary> public Task <T> RpcCall <T, K>(string address, K request, int waitTime = 0) { AChannel channel = this.service.GetChannel(address); ++this.requestId; byte[] requestBuffer = MongoHelper.ToBson(request); Opcode opcode = EnumHelper.FromString <Opcode>(request.GetType().Name); byte[] opcodeBuffer = BitConverter.GetBytes((ushort)opcode); byte[] idBuffer = BitConverter.GetBytes(this.requestId); channel.SendAsync(new List <byte[]> { opcodeBuffer, idBuffer, requestBuffer }); var tcs = new TaskCompletionSource <T>(); this.requestCallback[this.requestId] = (messageBytes, status) => { switch (status) { case RpcResponseStatus.Timeout: tcs.SetException(new Exception($"rpc timeout {opcode} {MongoHelper.ToJson(request)}")); return; case RpcResponseStatus.Exception: BinaryFormatter formatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.All)); Exception exception; using (MemoryStream stream = new MemoryStream(messageBytes, 6, messageBytes.Length - 6)) { exception = (Exception)formatter.Deserialize(stream); } tcs.SetException(exception); return; } // RpcResponseStatus.Succee T response = MongoHelper.FromBson <T>(messageBytes, 6); tcs.SetResult(response); }; if (waitTime > 0) { this.service.Timer.Add(TimeHelper.Now() + waitTime, () => { this.RpcCallback(channel, this.requestId, null, RpcResponseStatus.Timeout); }); } return(tcs.Task); }