private DynObject Transfer(ushort serverPort, byte[] buffer, int count) { //发送数据 Send(serverPort, buffer); ZmqMessage message = _ftpSocket.ReceiveMessage(new TimeSpan(0, 1, 30)); if (message.FrameCount == 0) { _isWorking = false; ReStart(); throw new TimeoutException("发送超时,请检查你的网络是否有问题,稍后重新上传"); } else { //反序列化,取出服务端响应数据 byte[] respData = message[message.FrameCount - 1].Buffer; TSerializer serializer = new TBinarySerializer(); serializer.FromBytes(respData); DynObject fileFragment = DynSerialize.ReadDynObject(serializer); serializer.Flush(); //105:发生异常 if ((byte)fileFragment["State"] == 105) { _isWorking = false; throw new ApplicationException(fileFragment["ExcepMsg"] as string); } return(fileFragment); } }
/// <summary> /// 处理返回消息 /// </summary> /// <param name="msgData">返回消息</param> private object DealRepMessage(byte[] msgData) { TSerializer serializerResp = new TBinarySerializer(); serializerResp.FromBytes(msgData); TMessage respMsg = serializerResp.ReadMessageBegin(); if (respMsg.Type == TMessageType.Exception) { this.RaiseDealMessageExceptionEvent(TApplicationException.Read(serializerResp)); serializerResp.ReadMessageEnd(); serializerResp.Flush(); return(null);; } if (respMsg.Type != TMessageType.RpcReply) { this.RaiseDealMessageExceptionEvent(new ApplicationException("非法的返回类型:" + respMsg.Type.ToString())); serializerResp.ReadMessageEnd(); serializerResp.Flush(); return(null); } string[] temp = respMsg.Name.Split('_'); DynMethodInstance dynMethodInstance = new DynMethodInstance(temp[0], temp[1]); try { dynMethodInstance.Result = DynSerialize.ReadResult(serializerResp, dynMethodInstance); } catch (Exception ex) { this.RaiseDealMessageExceptionEvent(ex); serializerResp.ReadMessageEnd(); serializerResp.Flush(); } // 消息结束 serializerResp.ReadMessageEnd(); serializerResp.Flush(); return(dynMethodInstance.Result); }
/// <summary> /// 向服务端发送下载文件的请求 /// </summary> /// <param name="destVPort">目的端口</param> /// <param name="downloadPath">要下载的文件在服务端的路径</param> /// <returns>将要下载文件的基本信息</returns> private DynObject RequestDownload(ushort destVPort, string downloadPath) { DynObject fileFragment = new DynObject("FileFragment"); fileFragment["Path"] = Path.GetDirectoryName(downloadPath); fileFragment["FileName"] = Path.GetFileName(downloadPath); fileFragment["Extension"] = Path.GetExtension(downloadPath); fileFragment["State"] = (byte)100; fileFragment["MsgID"] = -1; fileFragment["DataLength"] = 0; fileFragment["Data"] = null; //序列化要发送的数据 TSerializer serializer = new TBinarySerializer(); DynSerialize.WriteDynObject(serializer, fileFragment); byte[] buffer = serializer.ToBytes(); serializer.Flush(); Send(_serverPort, buffer); ZmqMessage msg = _ftpSocket.ReceiveMessage(new TimeSpan(0, 1, 30)); if (msg.FrameCount == 0) { _isWorking = false; ReStart(); throw new TimeoutException("发送超时,请检查你的网络是否有问题,稍后重新下载"); } //反序列化,服务器返回的数据 serializer = new TBinarySerializer(); serializer.FromBytes(msg[msg.FrameCount - 1].Buffer); DynObject respFragment = DynSerialize.ReadDynObject(serializer); serializer.Flush(); //发生异常 if ((byte)respFragment["State"] == 105) { _isWorking = false; throw new FtpException(respFragment["ExcepMsg"] as string); } return(respFragment); }
/// <summary> /// 处理接收到的数据 /// </summary> /// <param name="msgData">接收到的消息</param> private byte[] DealMessage(byte[] msgData) { //反序列化,取出数据 TSerializer serializer = new TBinarySerializer(); serializer.FromBytes(msgData); DynObject reqFragment = DynSerialize.ReadDynObject(serializer); serializer.Flush(); try { DynObject repFragment = OnFileDataReceived(reqFragment); //序列化并把数据返回给客户端 serializer = new TBinarySerializer(); DynSerialize.WriteDynObject(serializer, repFragment); byte[] repData = serializer.ToBytes(); serializer.Flush(); return(repData); } catch (Exception ex) { //如果服务端需要记录日志,则由本事件把异常信息发出 if (OnException != null) { OnException(ex); } _isRunning = false; DynObject repFragment = new DynObject("FileFragment"); repFragment["State"] = (byte)105; repFragment["ExcepMsg"] = "FtpServer端异常," + ex.Message; //序列化并把异常数据返回给客户端 serializer = new TBinarySerializer(); DynSerialize.WriteDynObject(serializer, repFragment); byte[] repData = serializer.ToBytes(); serializer.Flush(); return(repData); } }
/// <summary> /// 处理返回消息 /// </summary> /// <param name="msgData">返回消息</param> private object DealRepMessage(byte[] msgData, string msgID, out bool isReceive) { //初始化序列化容器 TSerializer serializerResp = new TBinarySerializer(); //将数据读入序列化容器 serializerResp.FromBytes(msgData); //从序列化容器中读取消息 TMessage respMsg = serializerResp.ReadMessageBegin(); //如果消息的id不对返回空值 if (msgID != respMsg.MsgID) { //空方法 serializerResp.ReadMessageEnd(); serializerResp.Flush(); isReceive = false; return(null); } //如果是异常消息 if (respMsg.Type == TMessageType.Exception) { TApplicationException appException = TApplicationException.Read(serializerResp); this.RaiseDealMessageExceptionEvent(appException); serializerResp.ReadMessageEnd(); serializerResp.Flush(); throw appException; } //如果消息是远程调用回应 if (respMsg.Type != TMessageType.RpcReply) { this.RaiseDealMessageExceptionEvent(new ApplicationException("非法的返回类型:" + respMsg.Type.ToString())); serializerResp.ReadMessageEnd(); serializerResp.Flush(); isReceive = true; return(null); } //构造方法的实例 string[] temp = respMsg.Name.Split('_'); DynMethodInstance dynMethodInstance = new DynMethodInstance(temp[0], temp[1]); try { dynMethodInstance.Result = DynSerialize.ReadResult(serializerResp, dynMethodInstance); } catch (Exception ex) { this.RaiseDealMessageExceptionEvent(ex); serializerResp.ReadMessageEnd(); serializerResp.Flush(); } // 消息结束 serializerResp.ReadMessageEnd(); serializerResp.Flush(); isReceive = true; return(dynMethodInstance.Result); }
/// <summary> /// 文件下载 /// </summary> /// <param name="recvAddress">服务端机器的地址</param> /// <param name="savePath">文件在本地的保存路径</param> /// <param name="downloadPath">要下载的文件在服务端的路径</param> public void FileDownload(string recvAddress, string savePath, string downloadPath) { #region 前置检查 if (_isWorking) { throw new FtpException("一个FtpClient不能同时执行多个任务"); } //验证本地是否已有同名文件 if (File.Exists(Path.Combine(savePath, Path.GetFileName(downloadPath)))) { throw new FtpException(savePath + "目录中已存在同名文件"); } #endregion 前置检查 #region 获取文件的基本信息 _remoteAddress = new VirtuaIP(recvAddress); _serverPort = GetServerPort("FileDownload"); _isWorking = true; //发送下载文件的请求 long fileSize = 0; //文件大小(字节) long remaining = 0; //剩余未下载的文件大小 DynObject fileFragment = RequestDownload(_serverPort, downloadPath); fileSize = remaining = (long)fileFragment["FileLength"]; #endregion 获取文件的基本信息 FileStream writeFileStream = null; _isCancelDownload = false; while (remaining >= 0 && _isWorking) { if (_isCancelDownload) { fileFragment["State"] = (byte)103; } switch ((byte)fileFragment["State"]) { case 100: string tempFile = Path.Combine(savePath, fileFragment["MD5"] + ".temp"); //如果存在该文件的临时文件,则进行断点续传,否则以MD5为名字创建临时文件开始传送数据 if (File.Exists(tempFile)) { writeFileStream = new FileStream(tempFile, FileMode.Open); fileFragment["MsgID"] = (int)(writeFileStream.Length / _bufferLength); fileFragment["State"] = (byte)101; fileFragment["Data"] = null; } else { writeFileStream = new FileStream(tempFile, FileMode.Create); fileFragment["MsgID"] = 0; fileFragment["State"] = (byte)101; fileFragment["Data"] = null; } remaining = fileSize - (int)fileFragment["MsgID"] * _bufferLength; break; case 101: //文件传送中 writeFileStream.Seek((int)fileFragment["MsgID"] * _bufferLength, SeekOrigin.Begin); writeFileStream.Write(fileFragment["Data"] as byte[], 0, (int)fileFragment["DataLength"]); remaining = fileSize - ((int)fileFragment["MsgID"] * _bufferLength + (int)fileFragment["DataLength"]); if (remaining <= 0) { //文件下载结束 fileFragment["State"] = (byte)102; writeFileStream.Flush(); writeFileStream.Close(); writeFileStream = null; _isWorking = false; //校验文件传送是否正确 string path = Path.Combine(savePath, fileFragment["MD5"] as string + ".temp"); string tempFileMD5 = GetMD5HashFromFile(path); if (tempFileMD5 == fileFragment["MD5"] as string) { File.Move(path, Path.Combine(savePath, fileFragment["FileName"] as string)); } else { File.Delete(path); throw new FtpException("文件未能成功下载"); } } fileFragment["MsgID"] = (int)fileFragment["MsgID"] + 1; fileFragment["DataLength"] = 0; fileFragment["Data"] = null; break; case 103: //中断文件传送 fileFragment["DataLength"] = 0; fileFragment["Data"] = null; writeFileStream.Flush(); writeFileStream.Close(); writeFileStream = null; _isWorking = false; break; case 105: //服务端发生异常 writeFileStream.Flush(); writeFileStream.Close(); writeFileStream = null; _isWorking = false; throw new FtpException(fileFragment["ExcepMsg"] as string); } //向外界通知文件床送进度 if (ProgressEvent != null) { ProgressEvent(fileSize, fileSize - remaining); } //发送请求下一个包数据(发生异常告诉对方关闭文件流) TSerializer serialize = new TBinarySerializer(); DynSerialize.WriteDynObject(serialize, fileFragment); byte[] buffer = serialize.ToBytes(); serialize.Flush(); Send(_serverPort, buffer); ZmqMessage message = _ftpSocket.ReceiveMessage(new TimeSpan(0, 1, 30)); if (message.FrameCount == 0) { writeFileStream.Close(); writeFileStream = null; _isWorking = false; ReStart(); throw new TimeoutException("发送超时,请检查你的网络是否有问题,稍后重新下载"); } serialize = new TBinarySerializer(); serialize.FromBytes(message[message.FrameCount - 1].Buffer); fileFragment = DynSerialize.ReadDynObject(serialize); serialize.Flush(); } }
/// <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; } } } }