/// <summary> /// 将网络信息解析为封包 /// </summary> /// <param name="buffer"></param> /// <returns></returns> public static Entity.PackedNetworkMessage Parse(byte[] buffer, IPEndPoint clientAddress) { if (!Test(buffer)) { return(null); } Entity.PackedNetworkMessage p = new PackedNetworkMessage() { RemoteIP = clientAddress, SendTimes = 0 }; p.PackageNo = BitConverter.ToUInt64(buffer, 1); //p. = BitConverter.ToUInt64(buffer, 9); //长度 p.PackageCount = BitConverter.ToInt32(buffer, 17); p.PackageIndex = BitConverter.ToInt32(buffer, 21); p.IsReceiveSignalRequired = buffer[21] == 1; p.Data = new byte[buffer.Length - PackageHeaderLength]; Array.Copy(buffer, PackageHeaderLength, p.Data, 0, p.Data.Length); return(p); }
/// <summary> /// 尝试将收到的消息解析为实体对象 /// </summary> /// <param name="buffer">封包消息</param> /// <param name="remoteEndPoint">远程主机的端点位置</param> /// <returns></returns> /// <remarks>如果是分包的消息且当前并未接收完全,则同样返回为空</remarks> public Message ResolveToMessage(byte[] buffer, IPEndPoint remoteEndPoint) { if (buffer == null || buffer.Length < 0) { return(null); } Message m = null; if (MessagePacker.Test(buffer)) { m = MessagePacker.TryToTranslateMessage(buffer, remoteEndPoint); if (m != null) { m.Host = LivedHost.GetHost(remoteEndPoint.Address.ToString()); //确认是否要发送回复 if (DetermineConfirm(m)) { Message cm = Message.Create(m.Host, remoteEndPoint, Config.GetRandomTick(), Config.GroupName, Config.NickName, FSLib.IPMessager.Define.Consts.Commands.RecvMsg, 0, m.PackageNo.ToString(), ""); Send(cm); } } } else if (MessagePackerV2.Test(buffer)) { PackedNetworkMessage pack = MessagePackerV2.Parse(buffer, remoteEndPoint); if (pack == null) { return(null); } if (DetermineConfirm(pack)) { //发送确认标志 Message cm = Message.Create(m.Host, remoteEndPoint, Config.GetRandomTick(), Config.GroupName, Config.NickName, FSLib.IPMessager.Define.Consts.Commands.Ex_PackageRecevied, 0, pack.PackageNo.ToString(), pack.PackageIndex.ToString()); Send(cm); } m = MessagePackerV2.TryToTranslateMessage(pack); if (m != null) { m.Host = LivedHost.GetHost(remoteEndPoint.Address.ToString()); //确认是否要发送回复 if (DetermineConfirm(m)) { Message cm = Message.Create(m.Host, remoteEndPoint, Config.GetRandomTick(), Config.GroupName, Config.NickName, FSLib.IPMessager.Define.Consts.Commands.RecvMsg, 0, m.PackageNo.ToString(), ""); Send(cm); } if (DetermineConfirm2(m)) { Message cm = Message.Create(m.Host, remoteEndPoint, Config.GetRandomTick(), Config.GroupName, Config.NickName, FSLib.IPMessager.Define.Consts.Commands.AnsReadMsg, 0, m.PackageNo.ToString(), ""); Send(cm); } } } return(m); }
/// <summary> /// 将数据信息压入列表 /// </summary> /// <param name="item"></param> void PushSendItemToList(PackedNetworkMessage item) { SendList.Add(item); }
/// <summary> /// 获得消息包的字节流 /// </summary> /// <param name="remoteIp">远程主机地址</param> /// <param name="packageNo">包编号</param> /// <param name="command">命令</param> /// <param name="options">参数</param> /// <param name="userName">用户名</param> /// <param name="hostName">主机名</param> /// <param name="content">正文消息</param> /// <param name="extendContents">扩展消息</param> /// <returns></returns> public static Entity.PackedNetworkMessage[] BuildNetworkMessage(IPEndPoint remoteIp, ulong packageNo, Define.Consts.Commands command, ulong options, string userName, string hostName, byte[] content, byte[] extendContents) { options |= (ulong)Define.Consts.Cmd_Send_Option.Content_Unicode; //每次发送所能容下的数据量 var maxBytesPerPackage = Define.Consts.MAX_UDP_PACKAGE_LENGTH - PackageHeaderLength; //压缩数据流 var ms = new System.IO.MemoryStream(); var zip = new System.IO.Compression.GZipStream(ms, System.IO.Compression.CompressionMode.Compress); var bw = new System.IO.BinaryWriter(zip, System.Text.Encoding.Unicode); //写入头部数据 bw.Write(packageNo); //包编号 bw.Write(((ulong)command) | options); //命令|选项 bw.Write(userName); //用户名 bw.Write(hostName); //主机名 bw.Write(content == null ? 0 : content.Length); //数据长度 //写入消息数据 if (content != null) bw.Write(content); bw.Write(extendContents == null ? 0 : extendContents.Length); //补充数据长度 if (extendContents != null) bw.Write(extendContents); bw.Close(); zip.Close(); ms.Flush(); ms.Seek(0, System.IO.SeekOrigin.Begin); //打包数据总量 var dataLength = (int)ms.Length; var packageCount = (int)Math.Ceiling(dataLength * 1.0 / maxBytesPerPackage); var pnma = new PackedNetworkMessage[packageCount]; for (var i = 0; i < packageCount; i++) { var count = i == packageCount - 1 ? dataLength - maxBytesPerPackage * (packageCount - 1) : maxBytesPerPackage; var buf = new byte[count + PackageHeaderLength]; buf[0] = VersionHeader; BitConverter.GetBytes(packageNo).CopyTo(buf, 1); BitConverter.GetBytes(dataLength).CopyTo(buf, 9); BitConverter.GetBytes(packageCount).CopyTo(buf, 13); BitConverter.GetBytes(i).CopyTo(buf, 17); buf[21] = Define.Consts.Check(options, Define.Consts.Cmd_All_Option.RequireReceiveCheck) ? (byte)1 : (byte)0; //包确认标志? ms.Read(buf, 32, buf.Length - 32); pnma[i] = new Entity.PackedNetworkMessage() { Data = buf, PackageCount = packageCount, PackageIndex = i, PackageNo = packageNo, RemoteIP = remoteIp, SendTimes = 0, Version = 2, IsReceiveSignalRequired = buf[21] == 1 }; } ms.Close(); return pnma; }
/// <summary> /// 将网络信息解析为封包 /// </summary> /// <param name="buffer"></param> /// <returns></returns> public static Entity.PackedNetworkMessage Parse(byte[] buffer, IPEndPoint clientAddress) { if (!Test(buffer)) return null; var p = new PackedNetworkMessage() { RemoteIP = clientAddress, SendTimes = 0 }; p.PackageNo = BitConverter.ToUInt64(buffer, 1); //p. = BitConverter.ToUInt64(buffer, 9); //长度 p.PackageCount = BitConverter.ToInt32(buffer, 17); p.PackageIndex = BitConverter.ToInt32(buffer, 21); p.IsReceiveSignalRequired = buffer[21] == 1; p.Data = new byte[buffer.Length - PackageHeaderLength]; Array.Copy(buffer, PackageHeaderLength, p.Data, 0, p.Data.Length); return p; }
/// <summary> /// 构造一个新的对象 /// </summary> public PackageSendEventArgs() { Package = null; }
/// <summary> /// 接收文件夹 /// </summary> /// <param name="client"></param> /// <param name="task"></param> /// <param name="item"></param> void PerformFileReceive_Folder(TcpClient client, FileTaskInfo task, FileTaskItem item) { TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Initializing); //创建网络流 NetworkStream netStream = null; try { netStream = client.GetStream(); } catch (Exception) { OnNetworkError(new EventArgs()); TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Failure); return; } bool updateTotal = item.TotalSize == 0; //是否在更新进度的时候需要更新总数 using (netStream) { //发送文件请求 PackedNetworkMessage pnm = MessagePacker.BuildNetworkMessage(Message.Create(task.RemoteHost, task.RemoteHost.HostSub.Ipv4Address, Config.GetRandomTick(), Config.HostName, Config.HostUserName, Consts.Commands.GetDirFiles, 0ul, string.Format("{0:x}:{1:x}:0:", task.PackageID, item.Index), "")); if (!SendDataInBuffer(netStream, pnm.Data, pnm.Data.Length)) { return; //发送请求 } TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Processing); item.StartTime = DateTime.Now; string filename; ulong size; bool isFolder, isRet; Stack <string> pathStack = new Stack <string>(); string currentPath = item.FullPath; while (client.Connected && item.State != FileTaskItemState.Canceling && ReadCmdHeader(netStream, task.RemoteHost, out filename, out size, out isFolder, out isRet)) { if (isRet) { if (pathStack.Count > 0) { currentPath = pathStack.Pop(); if (pathStack.Count == 0) { break; //Fixed: 当当前队列不再有信息时,其实接收已经完成了。因为当前队列中最后一个肯定是文件夹自己。 } } else { break; } } else if (isFolder) { //建立文件夹 if (!ProcessDirCmd(item, ref currentPath, pathStack, filename, updateTotal)) { TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Failure); return; } } else { //传文件 if (!ProcessFileTransfer(client, netStream, task, item, currentPath, filename, size, updateTotal)) { TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Failure); return; } } } netStream.Close(); } if (item.State == FileTaskItemState.Canceling) { TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Canceled); } else if (item.State != FileTaskItemState.Failure) { TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Finished); } }
/// <summary> /// 接收文件 /// </summary> /// <param name="client"></param> /// <param name="task"></param> /// <param name="item"></param> void PerformFileReceive_File(TcpClient client, FileTaskInfo task, FileTaskItem item) { TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Initializing); //创建文件 System.IO.FileInfo fileinfo = new FileInfo(item.FullPath); if (fileinfo.Exists) { item.CurrentFileTransfered = (ulong)fileinfo.Length; } if (item.CurrentFileSize <= item.CurrentFileTransfered) { TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Finished); return; } //创建文件 System.IO.FileStream writer = null; try { System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(item.FullPath)); writer = fileinfo.OpenWrite(); } catch (Exception) { OnFileSystemOperationError(new FileSystemOperationErrorEventArgs(FileSystemOperationType.CreateFile, item.FullPath, task.RemoteHost)); TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Failure); return; } //创建网络流 NetworkStream netStream = null; try { netStream = client.GetStream(); } catch (Exception) { OnNetworkError(new EventArgs()); TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Failure); return; } using (writer) { using (netStream) { //发送文件请求 PackedNetworkMessage pnm = MessagePacker.BuildNetworkMessage(Message.Create(task.RemoteHost, task.RemoteHost.HostSub.Ipv4Address, Config.GetRandomTick(), Config.HostName, Config.HostUserName, Consts.Commands.GetFileData, 0ul, string.Format("{0:x}:{1:x}:{2}", task.PackageID, item.Index, item.CurrentFileTransfered), "")); if (!SendDataInBuffer(netStream, pnm.Data, pnm.Data.Length)) { return; //发送请求 } TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Processing); item.StartTime = DateTime.Now; byte[] buffer = new byte[SendBuffer]; int length = buffer.Length; while (item.State != FileTaskItemState.Canceling && client.Connected && (length = ReceiveByBuffer(netStream, buffer, length)) > 0) { if (!WriteBufferToFile(task.RemoteHost, writer, item.FullPath, buffer, length)) { return; } item.CurrentFileTransfered += (ulong)length; item.FinishedSize += (ulong)length; //判断还有多少 length = buffer.Length; ulong restLength = item.CurrentFileSize - item.CurrentFileTransfered; if (restLength < (ulong)length) { length = (int)restLength; } } } } //判断是否完成 if (item.State == FileTaskItemState.Canceling) { TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Canceled); } else if (item.CurrentFileTransfered == item.CurrentFileSize) { TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Finished); } else { TaskManager.MarkReceiveTaskItemState(item, FileTaskItemState.Failure); } }
/// <summary> /// 获得消息包的字节流 /// </summary> /// <param name="remoteIp">远程主机地址</param> /// <param name="packageNo">包编号</param> /// <param name="command">命令</param> /// <param name="options">参数</param> /// <param name="userName">用户名</param> /// <param name="hostName">主机名</param> /// <param name="content">正文消息</param> /// <param name="extendContents">扩展消息</param> /// <returns></returns> public static Entity.PackedNetworkMessage[] BuildNetworkMessage(IPEndPoint remoteIp, ulong packageNo, Define.Consts.Commands command, ulong options, string userName, string hostName, byte[] content, byte[] extendContents) { options |= (ulong)Define.Consts.Cmd_Send_Option.Content_Unicode; //每次发送所能容下的数据量 int maxBytesPerPackage = Define.Consts.MAX_UDP_PACKAGE_LENGTH - PackageHeaderLength; //压缩数据流 System.IO.MemoryStream ms = new System.IO.MemoryStream(); System.IO.Compression.GZipStream zip = new System.IO.Compression.GZipStream(ms, System.IO.Compression.CompressionMode.Compress); System.IO.BinaryWriter bw = new System.IO.BinaryWriter(zip, System.Text.Encoding.Unicode); //写入头部数据 bw.Write(packageNo); //包编号 bw.Write(((ulong)command) | options); //命令|选项 bw.Write(userName); //用户名 bw.Write(hostName); //主机名 bw.Write(content == null ? 0 : content.Length); //数据长度 //写入消息数据 if (content != null) { bw.Write(content); } bw.Write(extendContents == null ? 0 : extendContents.Length); //补充数据长度 if (extendContents != null) { bw.Write(extendContents); } bw.Close(); zip.Close(); ms.Flush(); ms.Seek(0, System.IO.SeekOrigin.Begin); //打包数据总量 int dataLength = (int)ms.Length; int packageCount = (int)Math.Ceiling(dataLength * 1.0 / maxBytesPerPackage); Entity.PackedNetworkMessage[] pnma = new PackedNetworkMessage[packageCount]; for (int i = 0; i < packageCount; i++) { int count = i == packageCount - 1 ? dataLength - maxBytesPerPackage * (packageCount - 1) : maxBytesPerPackage; byte[] buf = new byte[count + PackageHeaderLength]; buf[0] = VersionHeader; BitConverter.GetBytes(packageNo).CopyTo(buf, 1); BitConverter.GetBytes(dataLength).CopyTo(buf, 9); BitConverter.GetBytes(packageCount).CopyTo(buf, 13); BitConverter.GetBytes(i).CopyTo(buf, 17); buf[21] = Define.Consts.Check(options, Define.Consts.Cmd_All_Option.RequireReceiveCheck) ? (byte)1 : (byte)0; //包确认标志? ms.Read(buf, 32, buf.Length - 32); pnma[i] = new Entity.PackedNetworkMessage() { Data = buf, PackageCount = packageCount, PackageIndex = i, PackageNo = packageNo, RemoteIP = remoteIp, SendTimes = 0, Version = 2, IsReceiveSignalRequired = buf[21] == 1 }; } ms.Close(); return(pnma); }