/// <summary> /// 头部写入请求 /// </summary> /// <param name="index"></param> internal WriteRequest(int index) { this.OnWrite = AutoCSer.Net.TcpServer.ServerCallback <ulong> .Null.Default; SubBuffer.Pool.GetPool(AutoCSer.Memory.BufferSize.Byte256).Get(ref Buffer); fixed(byte *bufferFixed = Buffer.GetFixedBuffer()) { byte *start = bufferFixed + Buffer.StartIndex; *(int *)start = Common.PuzzleValue; *(int *)(start + sizeof(int)) = (int)AutoCSer.IO.FileHead.DiskBlockFile; *(int *)(start + sizeof(int) * 2) = index; } Size = sizeof(int) * 2; }
private unsafe AppendBuffer getAppendBuffer(ref valueType value, BinarySerializer serializer, ref SubBuffer.PoolBufferFull buffer, out int size) { fixed(byte *bufferFixed = buffer.GetFixedBuffer()) { byte *start = bufferFixed + buffer.StartIndex; serializer.SerializeNotNull(ref value, start, buffer.PoolBuffer.Pool.Size, ClientConfig.BinarySerializeConfig); size = serializer.Stream.Data.CurrentIndex; if (serializer.Stream.Data.Data == start) { return new AppendBuffer { Buffer = new SubArray <byte> { Array = buffer.Buffer, Start = buffer.StartIndex, Length = size }, Index = size == Size ? Index : 0 } } ; else { return new AppendBuffer { Buffer = new SubArray <byte> { Array = serializer.Stream.Data.GetArray(), Length = size }, Index = size == Size ? Index : 0 } }; } } }
/// <summary> /// 文件尾部错误备份 /// </summary> /// <param name="buffer"></param> /// <param name="nextLength"></param> /// <param name="index"></param> /// <param name="count"></param> private void endError(ref SubBuffer.PoolBufferFull buffer, long nextLength, int index, int count) { if (!Config.IsIgnoreFileEndError) { throw new InvalidDataException(); } FileLength -= nextLength + count; using (FileStream endFileStream = new FileStream(FileName + ".ERROR" + Version.toString() + "_" + FileLength.toString(), FileMode.Create, FileAccess.Write, FileShare.None, bufferPool.Size, FileOptions.None)) { endFileStream.Write(buffer.Buffer, buffer.StartIndex + index, count); while (nextLength != 0) { count = fileStream.Read(buffer.Buffer, buffer.StartIndex, buffer.Length); endFileStream.Write(buffer.Buffer, buffer.StartIndex, count); nextLength -= count; } } fileStream.Seek(sizeof(int) * 2, SeekOrigin.Begin); fixed(byte *bufferFixed = buffer.GetFixedBuffer()) * (ulong *)(bufferFixed + (buffer.StartIndex + sizeof(int) * 2)) = ++Version; fileStream.Write(buffer.Buffer, buffer.StartIndex + sizeof(int) * 2, sizeof(ulong)); fileStream.SetLength(FileLength); fileStream.Flush(true); fileStream.Seek(0, SeekOrigin.End); IsDisposed = 0; }
/// <summary> /// 解析压缩数据 /// </summary> /// <param name="compressionBuffer"></param> /// <param name="dataSize"></param> /// <returns></returns> private bool load(ref SubBuffer.PoolBufferFull compressionBuffer, int dataSize) { if (compressionBuffer.Buffer == null) { return(false); } int bufferIndex = compressionBuffer.StartIndex, bufferSize = bufferIndex + dataSize; fixed(byte *bigBufferFixed = compressionBuffer.GetFixedBuffer()) { do { if (dataFileIdentity == writeIdentity) { bufferIndex += messages[writeMessageIndex].DeSerializeBuffer(bigBufferFixed + bufferIndex, compressionBuffer.Buffer, bufferIndex); nextWriteIndex(); } else { bufferIndex += messages[writeMessageIndex].Data.DeSerializeBuffer(bigBufferFixed + bufferIndex, compressionBuffer.Buffer, bufferIndex); } ++dataFileIdentity; }while (bufferIndex < bufferSize); } compressionBuffer.Free(); return(bufferIndex == bufferSize); }
/// <summary> /// 写入状态 /// </summary> /// <param name="buffer"></param> private void writeState(ref SubBuffer.PoolBufferFull buffer) { fixed(byte *stateBufferFixed = buffer.GetFixedBuffer()) { byte *start = stateBufferFixed + buffer.StartIndex; *(ulong *)start = identity; *(long *)(start + sizeof(ulong)) = dataFileLength; } if (stateFileStream.Length >= MaxStateFileSize) { stateFileStream.Dispose(); stateFileStream = null; FileInfo bakFile = new FileInfo(stateBackupFileName); if (bakFile.Exists) { bakFile.Delete(); } System.IO.File.Move(stateFileName, stateBackupFileName); stateFileStream = new FileStream(stateFileName, FileMode.CreateNew, FileAccess.Write, FileShare.Read, stateBufferSize, FileOptions.None); } stateFileStream.Write(buffer.Buffer, buffer.StartIndex, stateBufferSize); stateFileStream.Flush(true); StatePacketIndex.Set(identity, dataFileLength); }
/// <summary> /// 设置输出数据 /// </summary> /// <param name="value"></param> /// <param name="isAscii"></param> /// <param name="encoding"></param> internal unsafe void SetBody(string value, bool isAscii, ref EncodingCache encoding) { if (value.Length == 0) { SetBody(); } else { freeBody(); if (isAscii && encoding.IsCompatibleAscii != 0) { int size = value.Length; AutoCSer.SubBuffer.Pool.GetBuffer(ref SubBuffer, size); fixed(char *textFixed = value) fixed(byte *bufferFixed = SubBuffer.GetFixedBuffer()) { if (SubBuffer.PoolBuffer.Pool == null) { Body.Array = SubBuffer.Buffer; AutoCSer.Extensions.StringExtension.WriteBytes(textFixed, size, bufferFixed); SubBuffer.Buffer = null; Type = ResponseType.ByteArray; } else { Body.Set(SubBuffer.Buffer, SubBuffer.StartIndex, size); AutoCSer.Extensions.StringExtension.WriteBytes(textFixed, size, bufferFixed + Body.Start); Type = ResponseType.SubBuffer; } } } else { int size = encoding.GetByteCountNotNull(value); AutoCSer.SubBuffer.Pool.GetBuffer(ref SubBuffer, size); if (SubBuffer.PoolBuffer.Pool == null) { encoding.WriteBytesNotEmpty(value, Body.Array = SubBuffer.Buffer); SubBuffer.Buffer = null; Type = ResponseType.ByteArray; } else { Body.Set(SubBuffer.Buffer, SubBuffer.StartIndex, size); encoding.WriteBytesNotEmpty(value, Body.Array, Body.Start); Type = ResponseType.SubBuffer; } } } }
/// <summary> /// 字节拼接 /// </summary> /// <param name="values"></param> /// <param name="buffer"></param> /// <param name="length"></param> /// <param name="key"></param> private unsafe static void concat(string[] values, ref SubBuffer.PoolBufferFull buffer, int length, string key) { fixed(byte *bufferFixed = buffer.GetFixedBuffer()) { byte * write = bufferFixed + buffer.StartIndex, end = write + length; int isValue = 0, index = 0; MemoryMap utf8Map = new MemoryMap(isUtf8.Byte); foreach (string name in names) { string valueString = values[index]; if (!string.IsNullOrEmpty(valueString)) { if (isValue == 0) { isValue = 1; } else { *write++ = (byte)'&'; fixed(char *nameFixed = name) AutoCSer.Extensions.StringExtension.WriteBytes(nameFixed, name.Length, write); write += name.Length; *write++ = (byte)'='; fixed(char *valueFixed = valueString) { if (utf8Map.Get(index) == 0) { AutoCSer.Extensions.StringExtension.WriteBytes(valueFixed, valueString.Length, write); write += valueString.Length; } else { write += System.Text.Encoding.UTF8.GetBytes(valueFixed, valueString.Length, write, (int)(end - write)); } } } ++index; } if (isValue != 0) { *write++ = (byte)'&'; } *(int *)write = 'k' + ('e' << 8) + ('y' << 16) + ('=' << 24); write += sizeof(int); fixed(char *keyFixed = key) AutoCSer.Extensions.StringExtension.WriteBytes(keyFixed, key.Length, write); } }
/// <summary> /// 创建文件流 /// </summary> /// <param name="buffer"></param> /// <param name="version"></param> private void create(ref SubBuffer.PoolBufferFull buffer, ulong version) { if (buffer.Buffer == null) { bufferPool.Get(ref buffer); fixed(byte *bufferFixed = buffer.GetFixedBuffer()) { byte *bufferStart = bufferFixed + buffer.StartIndex; *(int *)bufferStart = FileHeader; *(ulong *)(bufferStart + sizeof(int) * 2) = Version; } fileStream.Write(buffer.Buffer, buffer.StartIndex, fileHeaderSize); FileLength = fileHeaderSize; IsDisposed = 0; }
/// <summary> /// MD5加密 /// </summary> /// <param name="md5"></param> /// <param name="value"></param> /// <param name="randomPrefix"></param> /// <param name="ticks"></param> /// <returns></returns> internal static byte[] Md5(MD5CryptoServiceProvider md5, string value, ulong randomPrefix, long ticks) { SubBuffer.PoolBufferFull buffer = default(SubBuffer.PoolBufferFull); SubBuffer.Pool.GetBuffer(ref buffer, (value.Length << 1) + (sizeof(ulong) + sizeof(long))); try { fixed(char *valueFixed = value) fixed(byte *dataFixed = buffer.GetFixedBuffer()) { byte *start = dataFixed + buffer.StartIndex; *(ulong *)start = randomPrefix; *(long *)(start + sizeof(ulong)) = ticks; AutoCSer.Extensions.StringExtension.SimpleCopyNotNull64(valueFixed, (char *)(start + (sizeof(ulong) + sizeof(long))), value.Length); } return(md5.ComputeHash(buffer.Buffer, buffer.StartIndex, (value.Length << 1) + (sizeof(ulong) + sizeof(long)))); } finally { buffer.PoolBuffer.Free(); } }
/// <summary> /// 写入数据包索引信息 /// </summary> /// <param name="buffer"></param> private void writeIndex(ref SubBuffer.PoolBufferFull buffer) { if (indexs.Length > 1) { FileInfo indexFileInfo = new FileInfo(getIndexFileName(identity - 1)); if (indexFileInfo.Exists) { indexFileInfo.Delete(); } using (FileStream indexFileStream = new FileStream(indexFileInfo.FullName, FileMode.CreateNew, FileAccess.Write, FileShare.Read, bufferPool.Size, FileOptions.None)) { int count = indexs.Length; fixed(byte *bufferFixed = buffer.GetFixedBuffer()) { byte *bufferStart = bufferFixed + buffer.StartIndex, write = bufferStart, end = bufferStart + buffer.Length; long fileIndex = 0; foreach (PacketIndex index in indexs.Array) { *(uint *)write = index.FileIdentity; *(int *)(write + sizeof(int)) = (int)(index.FileIndex - fileIndex); write += sizeof(int) * 2; fileIndex = index.FileIndex; if (write == end) { indexFileStream.Write(buffer.Buffer, buffer.StartIndex, buffer.Buffer.Length); write = bufferStart; } if (--count == 0) { break; } } if ((count = (int)(write - bufferStart)) != 0) { indexFileStream.Write(buffer.Buffer, buffer.StartIndex, count); } } } indexs.Array[0].Set(baseIdentity); indexs.Length = 1; } }
/// <summary> /// 获取商品二维码URL /// </summary> /// <param name="product_id"></param> /// <returns></returns> public unsafe string GetProductUrl(string product_id) { ProductUrlSign sign = new ProductUrlSign { product_id = product_id }; sign.setConfig(this); SubBuffer.PoolBufferFull buffer = default(SubBuffer.PoolBufferFull); int length = Sign <ProductUrlSign> .GetData(sign, key, ref buffer); try { fixed(byte *bufferFixed = buffer.GetFixedBuffer()) { using (MD5 md5 = new MD5CryptoServiceProvider()) { return("weixin://wxpay/bizpayurl?" + MemoryExtensionWebClient.BytesToStringNotEmpty(bufferFixed + buffer.StartIndex, length) + "&sign=" + sign.sign); } } } finally { buffer.Free(); } }
/// <summary> /// HTTP 响应头部输出 /// </summary> /// <param name="response"></param> /// <returns></returns> private bool responseHeader(ref Response response) { try { if (!response.IsFile) { ResponseError(ResponseState.NotFound404); return true; } System.Net.Sockets.Socket socket; ResponseFlag responseFlag = response.Flag; if (response.Body.Length != 0 && Header.IsKeepAlive != 0 && (responseFlag & ResponseFlag.HeaderSize) != 0 && Header.IsRange == 0 && Header.Method != MethodType.HEAD) { if ((socket = Socket) == null) return false; Data = response.Body; Data.MoveStart(-response.HeaderSize); SendType = SendType.Next; Timeout = Config.GetTimeout(Data.Length); #if DOTNET2 SocketError socketError; IAsyncResult async = socket.BeginSend(Data.Array, Data.Start, Data.Length, SocketFlags.None, out socketError, onSendAsyncCallback, socket); if (socketError == SocketError.Success) { if (!async.CompletedSynchronously) Http.Header.ReceiveTimeout.Push(this, socket); return true; } return false; #else sendAsyncLock.EnterSleepFlag(); sendAsyncEventArgs.SetBuffer(Data.Array, Data.Start, Data.Length); if (socket.SendAsync(sendAsyncEventArgs)) { sendAsyncLock.SleepFlag = 0; Http.Header.ReceiveTimeout.Push(this, socket); sendAsyncLock.Exit(); return true; } sendAsyncLock.ExitSleepFlag(); if (--sendDepth == 0) { sendDepth = maxSendDepth; OnSendThreadArray.Default.CurrentThread.Add(this); return true; } return onSend(); #endif } ResponseSize = response.BodySize; fixed (byte* headerBufferFixed = Header.Buffer.GetFixedBuffer()) { byte* responseSizeFixed = headerBufferFixed + (Header.Buffer.StartIndex + Http.Header.ReceiveBufferSize); RangeLength responseSizeIndex, bodySizeIndex = new RangeLength(), rangeStartIndex = new RangeLength(), rangeEndIndex = new RangeLength(); ResponseState state = response.ResponseState; if (Header.IsRange != 0 && (responseFlag & ResponseFlag.IsPool) != 0) { if (Header.IsFormatRange != 0 || Header.FormatRange(ResponseSize)) { if (state == ResponseState.Ok200) { long rangeStart = Header.RangeStart, rangeEnd = Header.RangeEnd; rangeStartIndex = NumberExtension.ToBytes((ulong)rangeStart, responseSizeFixed + 20 * 2); rangeEndIndex = NumberExtension.ToBytes((ulong)rangeEnd, responseSizeFixed + 20 * 3); bodySizeIndex = NumberExtension.ToBytes((ulong)ResponseSize, responseSizeFixed + 20); response.State = state = ResponseState.PartialContent206; ResponseSize = Header.RangeSize; } } else { ResponseSize = 0; ResponseError(ResponseState.RangeNotSatisfiable416); return true; } } if ((ulong)ResponseSize < 10) { *responseSizeFixed = (byte)((int)ResponseSize + '0'); responseSizeIndex = new RangeLength(0, 1); } else responseSizeIndex = NumberExtension.ToBytes((ulong)ResponseSize, responseSizeFixed); ResponseStateAttribute stateAttribute = EnumAttribute<ResponseState, ResponseStateAttribute>.Array((byte)state); if (stateAttribute == null) stateAttribute = EnumAttribute<ResponseState, ResponseStateAttribute>.Array((byte)ResponseState.ServerError500); int index = httpVersionSize + stateAttribute.Text.Length + contentLengthSize + responseSizeIndex.Length + 2 + 2; if (state == ResponseState.PartialContent206) { index += rangeSize + rangeStartIndex.Length + rangeEndIndex.Length + bodySizeIndex.Length + 2 + 2; } Cookie cookie = null; SubBuffer.PoolBufferFull buffer = GetBuffer(index = GetResponseHeaderIndex(response, index, ref cookie)); fixed (byte* bufferFixed = buffer.GetFixedBuffer()) { byte* bufferStart = bufferFixed + buffer.StartIndex, write = bufferStart + httpVersionSize; writeHttpVersion(bufferStart); stateAttribute.Write(write); writeContentLength(write += stateAttribute.Text.Length); AutoCSer.Memory.Common.SimpleCopyNotNull64(responseSizeFixed + responseSizeIndex.Start, write += contentLengthSize, responseSizeIndex.Length); *(short*)(write += responseSizeIndex.Length) = 0x0a0d; write += sizeof(short); if (state == ResponseState.PartialContent206) { writeRange(write); AutoCSer.Memory.Common.SimpleCopyNotNull64(responseSizeFixed + (rangeStartIndex.Start + 20 * 2), write += rangeSize, rangeStartIndex.Length); *(write += rangeStartIndex.Length) = (byte)'-'; AutoCSer.Memory.Common.SimpleCopyNotNull64(responseSizeFixed + (rangeEndIndex.Start + 20 * 3), ++write, rangeEndIndex.Length); *(write += rangeEndIndex.Length) = (byte)'/'; AutoCSer.Memory.Common.SimpleCopyNotNull64(responseSizeFixed + (bodySizeIndex.Start + 20), ++write, bodySizeIndex.Length); *(short*)(write += bodySizeIndex.Length) = 0x0a0d; write += sizeof(short); } index = (int)(CreateResponseHeader(response, cookie, write, index) - bufferStart); // if (checkIndex != index) // { // Server.RegisterServer.TcpServer.Log.add(Log.Type.Fatal, "responseHeader checkIndex[" + checkIndex.toString() + "] != index[" + index.toString() + @"] //" + System.Text.Encoding.ASCII.GetString(buffer.Buffer, buffer.StartIndex, index)); // } if (ResponseSize != 0) { switch (response.Type) { case ResponseType.ByteArray: if (buffer.Length - index >= (int)ResponseSize) { System.Buffer.BlockCopy(response.Body.Array, state == ResponseState.PartialContent206 ? (int)Header.RangeStart : 0, buffer.Buffer, buffer.StartIndex + index, (int)ResponseSize); index += (int)ResponseSize; ResponseSize = 0; } break; case ResponseType.SubByteArray: if (Header.IsKeepAlive != 0 && (responseFlag & ResponseFlag.CanHeaderSize) != 0 && index <= response.Body.Start && Header.IsRange == 0) { if ((socket = Socket) == null) return false; fixed (byte* bodyFixed = response.Body.GetFixedBuffer()) AutoCSer.Memory.Common.CopyNotNull(bufferStart, bodyFixed + response.Body.Start - index, index); response.SetHeaderSize(index); Data = response.Body; Data.MoveStart(-response.HeaderSize); SendType = SendType.Next; Timeout = Config.GetTimeout(Data.Length); #if DOTNET2 SocketError socketError; IAsyncResult async = socket.BeginSend(Data.Array, Data.Start, Data.Length, SocketFlags.None, out socketError, onSendAsyncCallback, socket); if (socketError == SocketError.Success) { if (!async.CompletedSynchronously) Http.Header.ReceiveTimeout.Push(this, socket); return true; } return false; #else sendAsyncLock.EnterSleepFlag(); sendAsyncEventArgs.SetBuffer(Data.Array, Data.Start, Data.Length); if (socket.SendAsync(sendAsyncEventArgs)) { sendAsyncLock.SleepFlag = 0; Http.Header.ReceiveTimeout.Push(this, socket); sendAsyncLock.Exit(); return true; } sendAsyncLock.ExitSleepFlag(); if (--sendDepth == 0) { sendDepth = maxSendDepth; OnSendThreadArray.Default.CurrentThread.Add(this); return true; } return onSend(); #endif } goto COPY; case ResponseType.SubBuffer: COPY: if (buffer.Length - index >= (int)ResponseSize) { System.Buffer.BlockCopy(response.Body.Array, state == ResponseState.PartialContent206 ? response.Body.Start + (int)Header.RangeStart : response.Body.Start, buffer.Buffer, buffer.StartIndex + index, (int)ResponseSize); index += (int)ResponseSize; ResponseSize = 0; } break; } } } if ((socket = Socket) != null) { if (ResponseSize == 0) SendType = SendType.Next; else { this.HttpResponse = response; SendType = SendType.Body; response = null; } Data.Set(buffer.Buffer, buffer.StartIndex, index); Timeout = Config.GetTimeout(Data.Length); #if DOTNET2 SocketError socketError; IAsyncResult async = socket.BeginSend(Data.Array, Data.Start, index, SocketFlags.None, out socketError, onSendAsyncCallback, socket); if (socketError == SocketError.Success) { if (!async.CompletedSynchronously) Http.Header.ReceiveTimeout.Push(this, socket); return true; } return false; #else sendAsyncLock.EnterSleepFlag(); sendAsyncEventArgs.SetBuffer(Data.Array, Data.Start, index); if (socket.SendAsync(sendAsyncEventArgs)) { sendAsyncLock.SleepFlag = 0; Http.Header.ReceiveTimeout.Push(this, socket); sendAsyncLock.Exit(); return true; } sendAsyncLock.ExitSleepFlag(); if (--sendDepth == 0) { sendDepth = maxSendDepth; OnSendThreadArray.Default.CurrentThread.Add(this); return true; } return onSend(); #endif } } } catch (Exception error) { Server.RegisterServer.TcpServer.Log.Exception(error, null, LogLevel.Exception | LogLevel.AutoCSer); } finally { Http.Response.Push(ref response); } return false; }
/// <summary> /// 接收数据 /// </summary> /// <typeparam name="outputParameterType"></typeparam> /// <param name="commandInfo"></param> /// <param name="outputParameter"></param> /// <param name="clientBuffer"></param> private unsafe void receive <outputParameterType>(TcpServer.CommandInfoBase commandInfo, ref outputParameterType outputParameter, ref ClientBuffer clientBuffer) where outputParameterType : struct { int compressionDataSize, dataSize = 0, nextSize, receiveSize = Socket.Receive(Buffer.Buffer, Buffer.StartIndex, Buffer.Length, SocketFlags.None, out clientBuffer.SocketError); ++ReceiveCount; if (receiveSize >= sizeof(int) * 2) { fixed(byte *bufferFixed = Buffer.GetFixedBuffer()) { byte *start = bufferFixed + Buffer.StartIndex; if ((compressionDataSize = *(int *)start) > 0) { if ((nextSize = compressionDataSize + sizeof(int) - receiveSize) == 0) { clientBuffer.IsError = false; if (ReceiveMarkData != 0) { Mark(Buffer.Buffer, ReceiveMarkData, Buffer.StartIndex + sizeof(int), compressionDataSize); } clientBuffer.SetReceiveData(ref Buffer, compressionDataSize); deSerialize(commandInfo, ref outputParameter, ref clientBuffer); return; } if (nextSize > 0 && clientBuffer.SocketError == SocketError.Success) { if (nextSize <= Buffer.Length) { goto RECEIVE; } else { goto BIGBUFFER; } } } else if (compressionDataSize < 0) { if ((compressionDataSize = -compressionDataSize) <= (dataSize = *(int *)(start + sizeof(int)))) { if ((nextSize = compressionDataSize + sizeof(int) * 2 - receiveSize) == 0) { clientBuffer.IsError = false; if (ReceiveMarkData != 0) { Mark(Buffer.Buffer, ReceiveMarkData, Buffer.StartIndex + sizeof(int) * 2, compressionDataSize); } if (clientBuffer.DeCompressReceiveData(ref Buffer, compressionDataSize, dataSize)) { deSerialize(commandInfo, ref outputParameter, ref clientBuffer); } return; } if (nextSize > 0) { if (nextSize <= Buffer.Length) { goto RECEIVE; } else { goto BIGBUFFER; } } } } else if (receiveSize == sizeof(int) * 2) { clientBuffer.ReturnType = (TcpServer.ReturnType)(*(start + sizeof(int))); return; } } } clientBuffer.ReturnType = TcpServer.ReturnType.ClientReceiveError; return; BIGBUFFER: clientBuffer.CopyBufferData(ref Buffer, receiveSize + nextSize, receiveSize); if (clientBuffer.CopyBuffer.Length > SendBufferMaxSize) { do { int count = Socket.Receive(Buffer.Buffer, Buffer.StartIndex + receiveSize, nextSize, SocketFlags.None, out clientBuffer.SocketError); ++ReceiveCount; if ((nextSize -= count) == 0) { clientBuffer.IsError = false; if (dataSize == 0) { if (ReceiveMarkData != 0) { Mark(clientBuffer.CopyBuffer.Buffer, ReceiveMarkData, clientBuffer.CopyBuffer.StartIndex + sizeof(int), compressionDataSize); } clientBuffer.SetReceiveData(compressionDataSize); deSerialize(commandInfo, ref outputParameter, ref clientBuffer); } else { if (ReceiveMarkData != 0) { Mark(clientBuffer.CopyBuffer.Buffer, ReceiveMarkData, clientBuffer.CopyBuffer.StartIndex + sizeof(int) * 2, compressionDataSize); } if (clientBuffer.DeCompressReceiveData(compressionDataSize, dataSize)) { deSerialize(commandInfo, ref outputParameter, ref clientBuffer); } } return; } if (count <= 0 || clientBuffer.SocketError != SocketError.Success) { clientBuffer.ReturnType = TcpServer.ReturnType.ClientReceiveError; return; } receiveSize += count; }while (true); } Buffer.Free(); clientBuffer.CopyBuffer.CopyToClear(ref Buffer); RECEIVE: do { int count = Socket.Receive(Buffer.Buffer, Buffer.StartIndex + receiveSize, nextSize, SocketFlags.None, out clientBuffer.SocketError); ++ReceiveCount; if ((nextSize -= count) == 0) { clientBuffer.IsError = false; if (dataSize == 0) { if (ReceiveMarkData != 0) { Mark(Buffer.Buffer, ReceiveMarkData, Buffer.StartIndex + sizeof(int), compressionDataSize); } clientBuffer.SetReceiveData(ref Buffer, compressionDataSize); deSerialize(commandInfo, ref outputParameter, ref clientBuffer); } else { if (ReceiveMarkData != 0) { Mark(Buffer.Buffer, ReceiveMarkData, Buffer.StartIndex + sizeof(int) * 2, compressionDataSize); } if (clientBuffer.DeCompressReceiveData(ref Buffer, compressionDataSize, dataSize)) { deSerialize(commandInfo, ref outputParameter, ref clientBuffer); } } return; } if (count <= 0 || clientBuffer.SocketError != SocketError.Success) { clientBuffer.ReturnType = TcpServer.ReturnType.ClientReceiveError; return; } receiveSize += count; }while (true); }
private static readonly SubBuffer.Pool stringBufferPool = SubBuffer.Pool.GetPool(AutoCSer.Memory.BufferSize.Kilobyte32);//4097 * 8 /// <summary> /// LZW压缩解码 /// </summary> /// <param name="input">输入数据</param> /// <param name="output">输出数据缓冲</param> /// <param name="size">编码长度</param> /// <returns>解码数据长度,失败返回-1</returns> private unsafe static int lzwDecode(byte[] input, byte *output, byte size) { int tableSize = (int)size + 1; short clearIndex = (short)(1 << size), nextIndex = clearIndex; SubBuffer.PoolBufferFull stringBuffer = default(SubBuffer.PoolBufferFull); stringBufferPool.Get(ref stringBuffer); try { fixed(byte *inputFixed = input, stringFixed = stringBuffer.GetFixedBuffer()) { byte *nextStrings = null, stringStart = stringFixed + stringBuffer.StartIndex; byte *currentInput = inputFixed, inputEnd = inputFixed + input.Length; byte *currentOutput = output, outputEnd = output + Writer.LzwEncodeTableBufferPool.Size; int valueBits = 0, inputSize = 0, inputOffset = (int)inputEnd & (sizeof(ulong) - 1), startSize = tableSize; ulong inputValue = 0, inputMark = ushort.MaxValue, startMark = ((ulong)1UL << startSize) - 1; short endIndex = (short)(clearIndex + 1), prefixIndex, currentIndex = 0; if (inputOffset == 0) { inputEnd -= sizeof(ulong); inputOffset = sizeof(ulong); } else { inputEnd -= inputOffset; } if (size == 1) { ++startSize; } while (currentIndex != endIndex) { if (valueBits >= startSize) { prefixIndex = (short)(inputValue & startMark); valueBits -= startSize; inputValue >>= startSize; } else { if (currentInput > inputEnd) { return(-1); } ulong nextValue = *(ulong *)currentInput; prefixIndex = (short)((inputValue | (nextValue << valueBits)) & startMark); inputValue = nextValue >> -(valueBits -= startSize); valueBits += sizeof(ulong) << 3; if (currentInput == inputEnd && (valueBits -= (sizeof(ulong) - inputOffset) << 3) < 0) { return(-1); } currentInput += sizeof(ulong); } if (prefixIndex == clearIndex) { continue; } if (prefixIndex == endIndex) { break; } if (currentOutput == outputEnd) { return(-1); } AutoCSer.Memory.Common.Clear((ulong *)stringStart, 4097); inputSize = startSize; inputMark = startMark; nextIndex = (short)(endIndex + 1); *(short *)(nextStrings = stringStart + (nextIndex << 3)) = prefixIndex; *(short *)(nextStrings + 2) = prefixIndex; *(int *)(nextStrings + 4) = 2; *currentOutput++ = (byte)prefixIndex; do { if (valueBits >= inputSize) { currentIndex = (short)(inputValue & inputMark); valueBits -= inputSize; inputValue >>= inputSize; } else { if (currentInput > inputEnd) { return(-1); } ulong nextValue = *(ulong *)currentInput; currentIndex = (short)((inputValue | (nextValue << valueBits)) & inputMark); inputValue = nextValue >> -(valueBits -= inputSize); valueBits += sizeof(ulong) << 3; if (currentInput == inputEnd && (valueBits -= (sizeof(ulong) - inputOffset) << 3) < 0) { return(-1); } currentInput += sizeof(ulong); } *(short *)(nextStrings += 8) = currentIndex; if (currentIndex < clearIndex) { if (currentOutput == outputEnd) { return(-1); } *(short *)(nextStrings + 2) = currentIndex; *(int *)(nextStrings + 4) = 2; *currentOutput++ = (byte)currentIndex; } else if (currentIndex > endIndex) { byte *currentString = stringStart + (currentIndex << 3); int outputCount = *(int *)(currentString + 4); if (outputCount == 0) { return(-1); } *(short *)(nextStrings + 2) = *(short *)(currentString + 2); *(int *)(nextStrings + 4) = outputCount + 1; if ((currentOutput += outputCount) > outputEnd) { return(-1); } do { *--currentOutput = *(currentString + 2 + 8); prefixIndex = *(short *)currentString; if (prefixIndex < clearIndex) { break; } currentString = stringStart + (prefixIndex << 3); }while (true); *--currentOutput = (byte)prefixIndex; currentOutput += outputCount; } else { break; } prefixIndex = currentIndex; if (nextIndex++ == (short)inputMark) { if (inputSize == 12) { return(-1); } inputMark <<= 1; ++inputSize; ++inputMark; } }while (true); } return((int)(currentOutput - output)); } } finally { stringBufferPool.Push(ref stringBuffer); } }
/// <summary> /// 获取数据包索引信息 /// </summary> /// <param name="identity">需要定位的数据标识</param> /// <param name="startIdentity"></param> /// <param name="fileIndex"></param> /// <returns></returns> internal bool GetIndex(ulong identity, ref ulong startIdentity, ref long fileIndex) { startIdentity = identity & (ulong.MaxValue - (DataCountPerFile - 1)); uint fileIdentity = (uint)identity & (DataCountPerFile - 1); if (fileIdentity == 0) { fileIndex = 0; return(true); } ulong baseIdentity = startIdentity; if (this.baseIdentity == startIdentity) { int length = indexs.Length; if (length > 1) { #region 二分查找当前数据文件数据包索引信息 int start = 0, average; PacketIndex[] indexArray = indexs.Array; do { if (identity > indexArray[average = start + ((length - start) >> 1)].Identity) { start = average + 1; } else { length = average; } }while (start != length); if (identity != indexArray[start].Identity) { --start; } indexArray[start].Get(out startIdentity, out fileIndex); if (this.baseIdentity == baseIdentity) { return(true); } #endregion } } FileInfo dataFileInfo = new FileInfo(GetFileName(identity)); if (dataFileInfo.Exists && dataFileInfo.Length != 0) { SubBuffer.PoolBufferFull buffer = default(SubBuffer.PoolBufferFull); SubBuffer.Pool.GetBuffer(ref buffer, createIndexBufferSize + sizeof(int)); try { fixed(byte *bufferFixed = buffer.GetFixedBuffer()) { byte *bufferStart = bufferFixed + buffer.StartIndex; #region 从索引数据文件获取数据包索引信息 FileInfo indexFileInfo = new FileInfo(getIndexFileName(identity)); if (indexFileInfo.Exists && indexFileInfo.Length >= sizeof(int) * 2) { uint lastFileIdentity = 0; fileIndex = 0; using (FileStream indexFileStream = new FileStream(indexFileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, createIndexBufferSize, FileOptions.None)) { do { int readSize = indexFileStream.Read(buffer.Buffer, buffer.StartIndex, createIndexBufferSize); if (readSize <= 0) { break; } byte *read = bufferStart, end = bufferStart + readSize; do { if (*(uint *)read < fileIdentity) { lastFileIdentity = *(uint *)read; fileIndex += *(int *)(read + sizeof(int)); } else { if (*(uint *)read == fileIdentity) { lastFileIdentity = *(uint *)read; fileIndex += *(int *)(read + sizeof(int)); } startIdentity = baseIdentity + lastFileIdentity; return(true); } }while ((read += sizeof(int) * 2) < end); }while (true); } startIdentity = baseIdentity + lastFileIdentity; return(true); } #endregion #region 从数据文件获取数据包索引信息 int bufferIndex = 0, dataSize; fileIndex = 0; startIdentity = baseIdentity; using (FileStream fileStream = new FileStream(dataFileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, createIndexBufferSize, FileOptions.None)) { long nextFileSize = fileStream.Length; do { int endBufferIndex = fileStream.Read(buffer.Buffer, buffer.StartIndex + bufferIndex, createIndexBufferSize - bufferIndex); nextFileSize -= endBufferIndex; endBufferIndex += bufferIndex - sizeof(int) * 3; bufferIndex = 0; do { byte *read = bufferStart + bufferIndex; dataSize = *(int *)read; ulong nextIdentity = startIdentity + *(uint *)(read + (dataSize < 0 ? sizeof(int) * 2 : sizeof(int))); if (nextIdentity >= identity) { if (nextIdentity == identity) { startIdentity = nextIdentity; bufferIndex += dataSize < 0 ? (-dataSize + PacketHeaderSize + sizeof(int)) : (dataSize + PacketHeaderSize); } fileIndex += bufferIndex; return(true); } startIdentity = nextIdentity; bufferIndex += dataSize < 0 ? (-dataSize + PacketHeaderSize + sizeof(int)) : (dataSize + PacketHeaderSize); }while (bufferIndex <= endBufferIndex); fileIndex += bufferIndex; switch (dataSize = bufferIndex - endBufferIndex) { case 1: case 2: case 3: *(ulong *)bufferStart = *(ulong *)(bufferStart + bufferIndex); *(uint *)(bufferStart + sizeof(ulong)) = *(uint *)(bufferStart + (bufferIndex + sizeof(ulong))); bufferIndex = sizeof(int) * 3 - dataSize; break; case 4: case 5: case 6: case 7: *(ulong *)bufferStart = *(ulong *)(bufferStart + bufferIndex); bufferIndex = sizeof(int) * 3 - dataSize; break; case 8: case 9: case 10: case 11: *(uint *)bufferStart = *(uint *)(bufferStart + bufferIndex); bufferIndex = sizeof(int) * 3 - dataSize; break; case 12: bufferIndex = 0; break; default: fileStream.Seek(dataSize -= sizeof(int) * 3, SeekOrigin.Current); nextFileSize -= dataSize; bufferIndex = 0; break; } }while (nextFileSize > 0); } return(true); #endregion } } finally { buffer.Free(); } } return(false); }
/// <summary> /// 初始化 /// </summary> internal void Start() { int isDisposed = 1; SubBuffer.PoolBufferFull buffer = default(SubBuffer.PoolBufferFull); try { if (checkStateFile()) { byte[] stateData = new byte[stateBufferSize]; stateFileStream = new FileStream(stateFileName, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, stateBufferSize, FileOptions.None); stateFileStream.Seek(-stateBufferSize, SeekOrigin.End); stateFileStream.Read(stateData, 0, stateBufferSize); fixed(byte *stateDataFixed = stateData) { identity = *(ulong *)stateDataFixed; dataFileLength = *(long *)(stateDataFixed + sizeof(ulong)); } if (((uint)identity & (DataCountPerFile - 1)) == 0) { dataFileLength = 0; } if (dataFileLength == 0) { FileInfo dataFileInfo = new FileInfo(dataFileName); if (dataFileInfo.Exists) { if (dataFileInfo.Length == 0) { dataFileInfo.Delete(); } else { AutoCSer.IO.File.MoveBak(dataFileInfo.FullName); } } dataFileStream = new FileStream(dataFileInfo.FullName, FileMode.CreateNew, FileAccess.Write, FileShare.Read, bufferPool.Size, FileOptions.None); } else { FileInfo dataFileInfo = new FileInfo(dataFileName); if (!dataFileInfo.Exists) { Node.Cache.TcpServer.Log.Error("没有找到消息队列数据文件 " + dataFileInfo.FullName, LogLevel.Error | LogLevel.AutoCSer); return; } if (dataFileInfo.Length < dataFileLength) { Node.Cache.TcpServer.Log.Error("消息队列数据文件 " + dataFileInfo.FullName + " 大小错误 " + dataFileInfo.Length.toString() + " < " + dataFileLength.toString(), LogLevel.Error | LogLevel.AutoCSer); return; } dataFileStream = new FileStream(dataFileInfo.FullName, FileMode.Open, FileAccess.Write, FileShare.Read, bufferPool.Size, FileOptions.None); if (dataFileStream.Length > dataFileLength) { dataFileStream.SetLength(dataFileLength); dataFileStream.Flush(true); } dataFileStream.Seek(0, SeekOrigin.End); FileInfo indexFileInfo = new FileInfo(getIndexFileName(identity)); bufferPool.Get(ref buffer); fixed(byte *bufferFixed = buffer.GetFixedBuffer()) { byte *bufferStart = bufferFixed + buffer.StartIndex, end = bufferStart + buffer.Length; ulong baseIdentity = this.baseIdentity; if (indexFileInfo.Exists && indexFileInfo.Length >= sizeof(int) * 2) { #region 初始化数据文件数据包索引信息 int count = (int)(indexFileInfo.Length >> 3), index = 0; long fileIndex = 0; indexs = new LeftArray <PacketIndex>(count); PacketIndex[] indexArray = indexs.Array; using (FileStream indexFileStream = new FileStream(indexFileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, bufferPool.Size, FileOptions.None)) { do { indexFileStream.Read(buffer.Buffer, buffer.StartIndex, buffer.Length); byte *read = bufferStart; do { indexArray[index].Set(baseIdentity + *(uint *)read, fileIndex += *(int *)(read + sizeof(int))); if (++index == count) { break; } }while ((read += sizeof(int) * 2) != end); }while (index != count); } while (index != 0) { if ((fileIndex = indexArray[--index].FileIndex) == dataFileLength) { if (indexArray[index].Identity == identity) { indexs.Length = index + 1; } break; } if (fileIndex < dataFileLength) { break; } } #endregion } if (indexs.Length == 0) { #region 重建数据文件数据包索引信息 if (indexs.Array.Length == 0) { indexs = new LeftArray <PacketIndex>(1 << 10); } indexs.Array[0].Set(baseIdentity); indexs.Length = 1; int bufferIndex = 0, readBufferSize = Math.Min(buffer.Length, createIndexBufferSize), bufferEndIndex, dataSize; long nextFileSize = dataFileLength, fileIndex = 0; using (FileStream fileStream = new FileStream(dataFileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, readBufferSize, FileOptions.None)) { readBufferSize -= sizeof(int); do { bufferEndIndex = fileStream.Read(buffer.Buffer, buffer.StartIndex + bufferIndex, readBufferSize - bufferIndex); nextFileSize -= bufferEndIndex; bufferEndIndex += bufferIndex - sizeof(int) * 3; bufferIndex = 0; do { byte *read = bufferStart + bufferIndex; dataSize = *(int *)read; if (dataSize < 0) { baseIdentity += *(uint *)(read + sizeof(int) * 2); bufferIndex += -dataSize + PacketHeaderSize + sizeof(int); } else { baseIdentity += *(uint *)(read + sizeof(int)); bufferIndex += dataSize + PacketHeaderSize; } indexs.PrepLength(1); indexs.Array[indexs.Length].Set(baseIdentity, fileIndex + bufferIndex); ++indexs.Length; }while (bufferIndex <= bufferEndIndex); fileIndex += bufferIndex; switch (dataSize = bufferIndex - bufferEndIndex) { case 1: case 2: case 3: *(ulong *)bufferStart = *(ulong *)(bufferStart + bufferIndex); *(uint *)(bufferStart + sizeof(ulong)) = *(uint *)(bufferStart + (bufferIndex + sizeof(ulong))); bufferIndex = sizeof(int) * 3 - dataSize; break; case 4: case 5: case 6: case 7: *(ulong *)bufferStart = *(ulong *)(bufferStart + bufferIndex); bufferIndex = sizeof(int) * 3 - dataSize; break; case 8: case 9: case 10: case 11: *(uint *)bufferStart = *(uint *)(bufferStart + bufferIndex); bufferIndex = sizeof(int) * 3 - dataSize; break; case 12: bufferIndex = 0; break; default: fileStream.Seek(dataSize -= sizeof(int) * 3, SeekOrigin.Current); nextFileSize -= dataSize; bufferIndex = 0; break; } }while (nextFileSize > 0); } #endregion } } } } else { stateFileStream = new FileStream(stateFileName, FileMode.CreateNew, FileAccess.Write, FileShare.Read, stateBufferSize, FileOptions.None); FileInfo dataFileInfo = new FileInfo(dataFileName); if (dataFileInfo.Exists) { if (dataFileInfo.Length == 0) { dataFileInfo.Delete(); } else { AutoCSer.IO.File.MoveBak(dataFileInfo.FullName); } } dataFileStream = new FileStream(dataFileName, FileMode.CreateNew, FileAccess.Write, FileShare.Read, bufferPool.Size, FileOptions.None); } if (indexs.Array.Length == 0) { indexs = new LeftArray <PacketIndex>(1 << 10); } if (indexs.Length == 0) { indexs.Array[0].Set(baseIdentity); indexs.Length = 1; } writeHandle = write; StatePacketIndex.Set(identity, dataFileLength); AutoCSer.DomainUnload.Unloader.Add(disposeHandle, DomainUnload.Type.Action); isDisposed = 0; } finally { buffer.TryFree(); if (isDisposed == 0) { Interlocked.Exchange(ref isWrite, 0); onStart(); if (!bufferQueue.IsEmpty && Interlocked.CompareExchange(ref isWrite, 1, 0) == 0) { write(); } } else { indexs.Length = 0; Dispose(); } } }