/// <summary> /// 尝试将收到的网络包解析为实体 /// </summary> /// <param name="pack">收到的网络包</param> /// <returns></returns> /// <remarks>如果收到的包是分片包,且其所有子包尚未接受完全,则会返回空值</remarks> public static Msg TryToTranslateMessage(PacketNetWorkMsg pack) { if (pack == null || pack.PackageIndex > pack.PackageCount - 1) { return(null); } else if (pack.PackageCount == 1) { return(ParseToMessage(pack)); } else { lock (packageCache) { if (packageCache.ContainsKey(pack.PackageNo)) { PacketNetWorkMsg[] array = packageCache[pack.PackageNo]; array[pack.PackageIndex] = pack; //检测是否完整 if (Array.FindIndex(array, s => s == null) == -1) { packageCache.Remove(pack.PackageNo); return(ParseToMessage(array)); } else { return(null); } } else { PacketNetWorkMsg[] array = new PacketNetWorkMsg[pack.PackageCount]; array[pack.PackageIndex] = pack; packageCache.Add(pack.PackageNo, array); return(null); } } } }
/// <summary> /// 将网络信息解析为封包 /// </summary> /// <param name="buffer"></param> /// <returns></returns> public static PacketNetWorkMsg Parse(byte[] buffer, IPEndPoint clientAddress) { if (!Test(buffer)) { return(null); } PacketNetWorkMsg p = new PacketNetWorkMsg() { RemoteIP = clientAddress, SendTimes = 0 }; p.PackageNo = BitConverter.ToInt64(buffer, 1); //包编号 p.DataLength = (int)BitConverter.ToInt64(buffer, 9); //内容长度 p.PackageCount = BitConverter.ToInt32(buffer, 13); //分包总数 p.PackageIndex = BitConverter.ToInt32(buffer, 17); //索引 p.IsRequireReceiveCheck = 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="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 PacketNetWorkMsg[] BuildNetworkMessage(IPEndPoint remoteIp, long packageNo, Commands command, string userName, string hostName, Consts type, byte[] content, byte[] extendContents, bool RequireReceiveCheck) { //每次发送所能容下的数据量 int maxBytesPerPackage = (int)Consts.MAX_UDP_PACKAGE_LENGTH - PackageHeaderLength; //压缩数据流 var ms = new MemoryStream(); //var dest = new MemoryStream(); //var zip = new GZipStream(dest, CompressionMode.Compress); var bw = new BinaryWriter(ms, System.Text.Encoding.Unicode); //写入头部数据 bw.Write(packageNo); //包编号 bw.Write(userName); //用户名 bw.Write(hostName); //主机名 bw.Write((long)command); //命令 bw.Write((long)type); //数据类型 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); } ms.Flush(); ms.Seek(0, System.IO.SeekOrigin.Begin); byte[] ibuf = ms.ToArray(); var dest = new System.IO.MemoryStream(); GZipStream zipStream = new GZipStream(dest, CompressionMode.Compress, true); byte[] buff = new byte[1024]; int offset; ms.Seek(0, SeekOrigin.Begin); while ((offset = ms.Read(buff, 0, buff.Length)) > 0) { zipStream.Write(buff, 0, offset);//先把数据用二进制写入内存,然后在把它用zip压缩,获取压缩过后的二进制流dest } zipStream.Close(); bw.Close(); ms.Close(); dest.Seek(0, SeekOrigin.Begin); //打包数据总量 int dataLength = (int)dest.Length; int packageCount = (int)Math.Ceiling(dataLength * 1.0 / maxBytesPerPackage); PacketNetWorkMsg[] pnma = new PacketNetWorkMsg[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; //版本号 第1位 BitConverter.GetBytes(packageNo).CopyTo(buf, 1); //消息编号 第2到9位 long类型的整数 BitConverter.GetBytes(dataLength).CopyTo(buf, 9); //消息内容长度 第10到13位 int类型的整数 BitConverter.GetBytes(packageCount).CopyTo(buf, 13); //分包总数 第14位到第17位 int类型的整数 BitConverter.GetBytes(i).CopyTo(buf, 17); //分包编号 第18位到第21位 int类型的整数 buf[21] = RequireReceiveCheck ? (byte)1 : (byte)0; //是否回确认包 第22位 //第23到第31位是保留的(Reserved) dest.Read(buf, 32, buf.Length - 32); //第32字节以后是,具体的数据包 pnma[i] = new PacketNetWorkMsg() { Data = buf, PackageCount = packageCount, PackageIndex = i, PackageNo = packageNo, RemoteIP = remoteIp, SendTimes = 0, Version = 2, IsRequireReceiveCheck = buf[21] == 1 }; } return(pnma); }