/// <summary> /// 读取一个数据包 /// </summary> /// <param name="token"></param> /// <returns></returns> protected async Task <ArraySegment <byte> > ReadPackageAsync(CancellationToken token) { var stream = QpPackageHandler_Stream; if (stream == null) { throw new ArgumentNullException(nameof(QpPackageHandler_Stream)); } //最终包缓存 ArraySegment <byte> finalPackageBuffer; //是否正在读取拆分包 bool isReadingSplitPackage = false; int splitMsCapacity = 0; MemoryStream splitMs = null; while (true) { var currentRecvBuffer = recvBuffer; //读取包头 var ret = await readData(stream, currentRecvBuffer, 0, PACKAGE_TOTAL_LENGTH_LENGTH, token); if (token.IsCancellationRequested) { return(nullArraySegment); } if (ret == 0) { throw new IOException("未读取到数据!"); } if (ret < PACKAGE_TOTAL_LENGTH_LENGTH) { throw new ProtocolException(new ArraySegment <byte>(recvBuffer, 0, ret), $"包头读取错误!包头长度:{PACKAGE_TOTAL_LENGTH_LENGTH},读取数据长度:{ret}"); } var currentRecvBuffer2 = recvBuffer; //如果读取缓存数组对象变化 if (currentRecvBuffer != currentRecvBuffer2) { Array.Copy(currentRecvBuffer, currentRecvBuffer2, PACKAGE_TOTAL_LENGTH_LENGTH); } //包总长度 var packageTotalLength = ByteUtils.B2I_BE(recvBuffer, 0); if (packageTotalLength < PACKAGE_HEAD_LENGTH) { throw new ProtocolException(new ArraySegment <byte>(recvBuffer, 0, ret), $"包长度[{packageTotalLength}]必须大于等于{PACKAGE_HEAD_LENGTH}!"); } if (packageTotalLength > recvBuffer.Length) { throw new ProtocolException(new ArraySegment <byte>(recvBuffer, 0, ret), $"数据包总长度[{packageTotalLength}]大于缓存大小[{recvBuffer.Length}]"); } //包体长度 var packageBodyLength = packageTotalLength - PACKAGE_TOTAL_LENGTH_LENGTH; //读取包体 ret = await readData(stream, recvBuffer, PACKAGE_TOTAL_LENGTH_LENGTH, packageBodyLength, token); if (token.IsCancellationRequested) { return(nullArraySegment); } if (ret < packageBodyLength) { throw new ProtocolException(new ArraySegment <byte>(recvBuffer, 0, PACKAGE_HEAD_LENGTH + ret), $"包体读取错误!包体长度:{packageBodyLength},读取数据长度:{ret}"); } var currentPackageBuffer = new ArraySegment <byte>(recvBuffer, 0, packageTotalLength); //如果设置了压缩或者加密 if (options.InternalCompress || options.InternalEncrypt) { //如果设置了加密,则先解密 if (options.InternalEncrypt) { try { var retBuffer = dec.TransformFinalBlock(currentPackageBuffer.Array, PACKAGE_TOTAL_LENGTH_LENGTH + currentPackageBuffer.Offset, currentPackageBuffer.Count - PACKAGE_TOTAL_LENGTH_LENGTH); var currentBuffer = getFreeBuffer(currentPackageBuffer.Array, recvBuffer, recvBuffer2); packageTotalLength = PACKAGE_TOTAL_LENGTH_LENGTH + retBuffer.Length; writePackageTotalLengthToBuffer(currentBuffer, 0, packageTotalLength); Array.Copy(retBuffer, 0, currentBuffer, PACKAGE_TOTAL_LENGTH_LENGTH, retBuffer.Length); currentPackageBuffer = new ArraySegment <byte>(currentBuffer, 0, packageTotalLength); } catch (Exception ex) { throw ex; } } //如果设置了压缩,则先解压 if (options.InternalCompress) { var retBuffer = getFreeBuffer(currentPackageBuffer.Array, recvBuffer, recvBuffer2); var count = 0; using (var readMs = new MemoryStream(currentPackageBuffer.Array, PACKAGE_TOTAL_LENGTH_LENGTH + currentPackageBuffer.Offset, currentPackageBuffer.Count - PACKAGE_TOTAL_LENGTH_LENGTH, false)) using (var writeMs = new MemoryStream(retBuffer, 0, retBuffer.Length)) { using (var gzStream = new GZipStream(readMs, CompressionMode.Decompress, true)) gzStream.CopyTo(writeMs); count = Convert.ToInt32(writeMs.Position); } var currentBuffer = getFreeBuffer(retBuffer, recvBuffer, recvBuffer2); packageTotalLength = PACKAGE_TOTAL_LENGTH_LENGTH + count; writePackageTotalLengthToBuffer(currentBuffer, 0, packageTotalLength); Array.Copy(retBuffer, 0, currentBuffer, PACKAGE_TOTAL_LENGTH_LENGTH, count); currentPackageBuffer = new ArraySegment <byte>(currentBuffer, 0, packageTotalLength); } } var packageType = (QpPackageType)currentPackageBuffer.Array[currentPackageBuffer.Offset + PACKAGE_HEAD_LENGTH - 1]; //如果当前包是拆分包 if (packageType == QpPackageType.Split) { if (!isReadingSplitPackage) { var tmpPackageBodyLength = ByteUtils.B2I_BE(currentPackageBuffer.Array, currentPackageBuffer.Offset + PACKAGE_HEAD_LENGTH); splitMsCapacity = tmpPackageBodyLength; if (splitMsCapacity <= 0) { throw new IOException($"拆分包中包长度[{splitMsCapacity}]必须为正数!"); } if (splitMsCapacity > options.MaxPackageSize) { throw new IOException($"拆分包中包长度[{splitMsCapacity}]大于最大包大小[{options.MaxPackageSize}]"); } splitMs = new MemoryStream(splitMsCapacity); isReadingSplitPackage = true; } splitMs.Write(currentPackageBuffer.Array, currentPackageBuffer.Offset + PACKAGE_HEAD_LENGTH, currentPackageBuffer.Count - PACKAGE_HEAD_LENGTH); //如果拆分包已经读取完成 if (splitMs.Position >= splitMsCapacity) { finalPackageBuffer = new ArraySegment <byte>(splitMs.ToArray()); splitMs.Dispose(); if (LogUtils.LogSplit) { LogUtils.Log("{0}: [Recv-SplitPackage]Length:{1}", DateTime.Now, finalPackageBuffer.Count); } break; } } else { finalPackageBuffer = currentPackageBuffer; break; } } if (LogUtils.LogPackage) { LogUtils.Log( "{0}: [Recv-Package]Length:{1},Type:{2},Content:{3}", DateTime.Now, finalPackageBuffer.Count, (QpPackageType)finalPackageBuffer.Array[finalPackageBuffer.Offset + PACKAGE_HEAD_LENGTH - 1], LogUtils.LogContent ? BitConverter.ToString(finalPackageBuffer.Array, finalPackageBuffer.Offset, finalPackageBuffer.Count) : LogUtils.NOT_SHOW_CONTENT_MESSAGE); } return(new ArraySegment <byte>(finalPackageBuffer.Array, finalPackageBuffer.Offset, finalPackageBuffer.Count)); }