Example #1
0
        /// <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));
        }