/// <summary> /// 把异常信息传递到客户端 /// </summary> /// <param name="exceptionSource">错误源</param> /// <param name="msg">正常的消息头</param> /// <param name="exceptionMsg">异常信息</param> private byte[] ReturnExceptionToClient(string exceptionSource, TMessage msg, string exceptionMsg) { //把异常信息传递到客户端 TSerializer serializer = new TBinarySerializer(); TMessage exceptMsg = new TMessage(exceptionSource, TMessageType.Exception, msg.MsgID, msg.LiveLife, "", "", "", ""); serializer.WriteMessageBegin(exceptMsg); TApplicationException tAppException = new TApplicationException(TApplicationException.ExceptionType.Unknown, exceptionMsg); tAppException.Write(serializer); serializer.WriteMessageEnd(); //如果不是单向的,把异常返回,并跳出处理函数 byte[] respException = serializer.ToBytes(); serializer.Flush(); // 返回异常 return(respException); }
/// <summary> /// 远程方法调用 /// </summary> /// <param name="recvAddress">接收节点的虚拟IP地址,如3.1/param> /// <param name="interfaceName">接口名称</param> /// <param name="methodName">方法名称</param> /// <param name="paramDict">参数字段</param> /// <param name="messageType">消息类型</param> public void Call(string recvAddress, ushort destVPort, string interfaceName, string methodName, Dictionary <string, object> paramDict, TMessageType messageType = TMessageType.RpcCall) { try { VirtuaIP receiverVIP = new VirtuaIP(recvAddress); string msgID = Guid.NewGuid().ToString(); if (!InterfaceImplementMap.InterfaceAndImplementMap.ContainsKey(interfaceName)) { throw new ApplicationException("找不到接口" + interfaceName + "的具体实现!!"); } //本地应用端口随机获取,目标端口确定 TMessage reqMsg = new TMessage(interfaceName + "_" + methodName, messageType, msgID, -1, "", "", "", ""); DynMethodInstance dynMethodInstance = new DynMethodInstance(interfaceName, methodName); TSerializer serializerReq = new TBinarySerializer(); serializerReq.WriteMessageBegin(reqMsg); foreach (var para in paramDict) { dynMethodInstance[para.Key] = para.Value; } DynSerialize.WriteDynMethodInstance(serializerReq, dynMethodInstance); serializerReq.WriteMessageEnd(); byte[] reqData = serializerReq.ToBytes(); serializerReq.Flush(); Send(receiverVIP, destVPort, reqData); } catch (Exception ex) { this.RaiseDealMessageExceptionEvent(ex); throw new ApplicationException(ex.Message); } }
/// <summary> /// 远程方法调用 /// </summary> /// <param name="recvAddress">接收节点的虚拟IP地址,如3.1/param> /// <param name="interfaceName">接口名称</param> /// <param name="methodName">方法名称</param> /// <param name="paramDict">参数字段</param> /// <param name="liveLife">生命周期,以秒为单位</param> /// <param name="messageType">消息类型</param> /// <returns>服务端返回的数据或者null</returns> public object Call(string recvAddress, ushort destVPort, string interfaceName, string methodName, Dictionary <string, object> paramDict, short liveLife, TMessageType messageType = TMessageType.RpcCall) { object result = null; _msgID = _msgID < int.MaxValue ? ++_msgID : 0; try { VirtuaIP receiverVIP = new VirtuaIP(recvAddress); string msgID = _msgID.ToString(); if (!InterfaceImplementMap.InterfaceAndImplementMap.ContainsKey(interfaceName)) { throw new ApplicationException("找不到接口" + interfaceName + "的具体实现!"); } DynMethodInstance dynMethodInstance = new DynMethodInstance(interfaceName, methodName); TMessage reqMsg = new TMessage(interfaceName + "_" + methodName, messageType, msgID, liveLife, "", "", "", ""); TSerializer serializerReq = new TBinarySerializer(); //将消息头信息写入流 serializerReq.WriteMessageBegin(reqMsg); foreach (var para in paramDict) { dynMethodInstance[para.Key] = para.Value; } //将方法的实例写入流 DynSerialize.WriteDynMethodInstance(serializerReq, dynMethodInstance); //什么都不做 serializerReq.WriteMessageEnd(); //将消息流转换成二进制流 byte[] reqData = serializerReq.ToBytes(); serializerReq.Flush(); //发送消息 Send(receiverVIP, destVPort, reqData); var timeout = new TimeSpan(0, 0, liveLife); //创建一个 Stopwatch 实例:使用 StartNew() 会创建一个 Stopwatch 实例并马上开始计时,即等效于如下代码: //Stopwatch sw2 = new Stopwatch(); //sw2.Start(); var timer = Stopwatch.StartNew(); bool isReceive = false; do { ZmqMessage zmqMessage = _reqSocket.ReceiveMessage(timeout - timer.Elapsed); if (zmqMessage.FrameCount == 0) { throw new TimeoutException("调用超时,请检查网络是否联通!"); } else { //zmqMessage[zmqMessage.FrameCount - 1].Buffer 只需要处理zmqMessage中最后一帧,这一帧存的是消息中的数据部分 result = DealRepMessage(zmqMessage[zmqMessage.FrameCount - 1].Buffer, msgID, out isReceive); //消息ID不匹配且超时时间未到时,丢掉当前接收到的数据包,继续接受数据 if (isReceive) { return(result); } } }while (timer.Elapsed <= timeout); throw new TimeoutException("调用超时,请检查网络是否联通!"); } catch (Exception ex) { this.RaiseDealMessageExceptionEvent(ex); throw; } }
/// <summary> /// 重载父类方法 /// </summary> /// <param name="msgData">接收到的消息</param> private void DealMessage(object obj) { ZmqMessage zmqMessage = obj as ZmqMessage; //记录源地址和端口 VirtuaIP originVIP = new VirtuaIP(zmqMessage[1].Buffer); ushort originPort = (ushort)BitConverter.ToInt16(zmqMessage[3].Buffer, 0); byte[] requestData = zmqMessage[zmqMessage.FrameCount - 1].Buffer; if (requestData != null && requestData.Length >= 4) { TSerializer serializer = new TBinarySerializer(); serializer.FromBytes(requestData); // 获取消息 TMessage msg = serializer.ReadMessageBegin(); if (msg.Type == TMessageType.RpcCall || msg.Type == TMessageType.RpcOneway) { //获取方法信息构造Method string[] temp = msg.Name.Split('_'); DynMethodInstance methodInstance = null; try { methodInstance = DynSerialize.ReadDynMethodInstance(serializer, temp[0], temp[1]); serializer.ReadMessageEnd(); serializer.Flush(); Dictionary <string, object> paramValues = new Dictionary <string, object>(); //获取参数信 foreach (string paramName in methodInstance.DynMethod.GetParameterNames()) { paramValues[paramName] = methodInstance[paramName]; } string className = InterfaceImplementMap.InterfaceAndImplementMap[temp[0]]; string methodFullName = className + "_" + temp[1]; //方法调用 object ret = DynTypeManager.MethodHandler(null, methodFullName, paramValues); if (methodInstance.DynMethod.Result.DynType != DynType.Void) { methodInstance.Result = ret; } // 序列化返回结果 serializer = new TBinarySerializer(); TMessage respMsg = new TMessage(msg.Name, TMessageType.RpcReply, msg.MsgID, msg.LiveLife, "", "", "", ""); serializer.WriteMessageBegin(respMsg); DynSerialize.WriteResult(serializer, methodInstance); serializer.WriteMessageEnd(); byte[] respData = serializer.ToBytes(); serializer.Flush(); // 返回客户端 Send(originVIP, originPort, respData); } catch (Exception ex) { serializer.ReadMessageEnd(); serializer.Flush(); //如果服务端需要记录日志,则由本事件把异常信息发出 RaiseDealMessageExceptionEvent(ex); byte[] returnData = ReturnExceptionToClient("RpcServer.DealMessageException", msg, ex.Message); // 返回客户端 Send(originVIP, originPort, returnData); return; } } } }