public void CanWeClearBufferContent() { var settings = CreateSettings(1, 10, 1); var manager = new BufferManager(settings); byte[] test = manager.GetBuffer(10); test[0] = 0x01; Assert.NotNull(test); Assert.AreEqual(test.Length, 10); //we get the same length manager.FreeBuffer(ref test, true); test = manager.GetBuffer(10); Assert.True(test[0] == 0x00);//we got a cleared one }
public void CanWeAllocateBuffers() { var settings = CreateSettings(1, 10, 1); var manager = new BufferManager(settings); byte[] test = manager.GetBuffer(10); test[0] = 0x01; Assert.NotNull(test); Assert.AreEqual(test.Length, 10); //we get the same length manager.FreeBuffer(ref test); Assert.True(test == BufferManager.EmptyBuffer); //we aren't referencing it anymore test = manager.GetBuffer(10); Assert.True(test[0] == 0x01);//we got the same one back }
public void Write(ProtocolBufferWriter writer) { writer.WriteULong(EntityId); switch (Subtype) { case CallMethodMessageSubtype.MethodId: case CallMethodMessageSubtype.UnkPlusMethodId: writer.WriteUInt((uint)MethodId); break; case CallMethodMessageSubtype.MethodName: case CallMethodMessageSubtype.UnkPlusMethodName: writer.WriteString(MethodName); break; default: throw new Exception($"Invalid subtype ({Subtype}) for CallMethodMessage!"); } var buffer = BufferManager.RequestBuffer(); using (var bw = buffer.CreateWriter()) { bw.Write((byte)0x4F); // 'O' - Optimized Marshall Format Packet.Write(bw); bw.Write((byte)0x66); // 'f' - python payload finish mark writer.WriteArray(buffer.Buffer, buffer.BaseOffset, (int)bw.BaseStream.Position); } BufferManager.FreeBuffer(buffer); if (Subtype == CallMethodMessageSubtype.UnkPlusMethodId || Subtype == CallMethodMessageSubtype.UnkPlusMethodName) { writer.WriteUInt(UnknownValue); } }
private void TeardownEventArgs(SocketAsyncEventArgs args) { switch (args.LastOperation) { case SocketAsyncOperation.Receive: case SocketAsyncOperation.Send: BufferManager.FreeBuffer(args.GetUserToken <BufferData>()); args.SetBuffer(null, 0, 0); args.UserToken = null; break; case SocketAsyncOperation.Connect: args.RemoteEndPoint = null; break; } args.AcceptSocket = null; args.Completed -= OperationCompleted; lock (_socketAsyncEventArgsPool) _socketAsyncEventArgsPool.Push(args); }
public void Read(BinaryReader br) { if (br.BaseStream.Length < 4) { throw new Exception("Fragmented receive, should not happen! (4 size header)"); } Size = br.ReadUInt16(); Channel = br.ReadByte(); br.ReadByte(); // padding if (Size > br.BaseStream.Length) { Debugger.Break(); throw new Exception($"Fragmented receive, should not happen! Packet size: {Size} <-> Buffer length: {br.BaseStream.Length}"); } if (Channel == 0xFF) // Internal channel: Send timeout checking, ignore the packet { return; } if (Channel != 0) // 0 == ReliableStreamChannel (no extra data), Move message uses channels { SequenceNumber = br.ReadUInt32(); // Sequence number? if (previousValue - newValue < 0) { process packet; previousValue = newValue; } br.ReadInt32(); // 0xDEADBEEF br.ReadInt32(); // skip } var packetBeginPosition = br.BaseStream.Position; using (var reader = new ProtocolBufferReader(br, ProtocolBufferFlags.DontFragment)) { reader.ReadProtocolFlags(); reader.ReadPacketType(out ushort type, out bool compress); Type = (ClientMessageOpcode)type; Compress = compress; reader.ReadXORCheck((int)(br.BaseStream.Position - packetBeginPosition)); } var xorCheckPosition = (int)br.BaseStream.Position; var readBr = br; BufferData buffer = null; if (Compress) { var someType = br.ReadByte(); // 0 = No compression if (someType >= 2) { throw new Exception("Invalid compress type received!"); } if (someType == 1) { Debugger.Break(); // TODO: test var uncompressedSize = br.ReadInt32(); byte[] uncompressedData; var offset = 0; if (uncompressedSize > BufferManager.BlockSize) { uncompressedData = new byte[uncompressedSize]; } else { buffer = BufferManager.RequestBuffer(); uncompressedData = buffer.Buffer; offset = buffer.BaseOffset; } using (var deflateStream = new DeflateStream(br.BaseStream, CompressionMode.Decompress, true)) // TODO: test if the br.BaseStream is cool as the Stream input for the DeflateStream deflateStream.Read(uncompressedData, offset, uncompressedSize); readBr = buffer != null?buffer.GetReader() : new BinaryReader(new MemoryStream(uncompressedData, 0, uncompressedSize, false), Encoding.UTF8, false); } } // ReSharper disable SwitchStatementMissingSomeCases switch (Type) { case ClientMessageOpcode.Login: Message = new LoginMessage(); break; case ClientMessageOpcode.Move: Message = new MoveMessage(); break; case ClientMessageOpcode.CallServerMethod: Message = new CallServerMethodMessage(); break; case ClientMessageOpcode.Ping: Message = new PingMessage(); break; default: throw new Exception($"Unable to handle packet type {Type}, because it's a Server -> Client packet!"); } // ReSharper restore SwitchStatementMissingSomeCases using (var reader = new ProtocolBufferReader(readBr, ProtocolBufferFlags.DontFragment)) { reader.ReadProtocolFlags(); // Subtype and Message.Read() reader.ReadDebugByte(41); if ((Message.SubtypeFlags & ClientMessageSubtypeFlag.HasSubtype) == ClientMessageSubtypeFlag.HasSubtype) { Message.RawSubtype = reader.ReadByte(); if (Message.RawSubtype < Message.MinSubtype || Message.RawSubtype > Message.MaxSubtype) { throw new Exception("Invalid Subtype found!"); } } Message.Read(reader); reader.ReadDebugByte(42); reader.ReadXORCheck((int)br.BaseStream.Position - xorCheckPosition); } if (buffer != null) // If we requested a buffer for decompressing, free it { BufferManager.FreeBuffer(buffer); } }
public void Write(BinaryWriter bw) { var sizePosition = bw.BaseStream.Position; bw.Write((ushort)0); // Size placeholder bw.Write(Channel); bw.Write((byte)0); // padding if (Channel != 0) { bw.Write(SequenceNumber); // sequence num? bw.Write(0xDEADBEEF); // const bw.Write(0); // padding } var packetBeginPosition = (int)bw.BaseStream.Position; var packetBuffer = BufferManager.RequestBuffer(); int uncompressedSize; using (var ms = new MemoryStream(packetBuffer.Buffer, packetBuffer.BaseOffset, packetBuffer.MaxLength, true)) { using (var packetWriter = new BinaryWriter(ms, Encoding.UTF8, true)) { using (var writer = new ProtocolBufferWriter(packetWriter, ProtocolBufferFlags.DontFragment)) { writer.WriteProtocolFlags(); writer.WriteDebugByte(41); if ((Message.SubtypeFlags & ClientMessageSubtypeFlag.HasSubtype) == ClientMessageSubtypeFlag.HasSubtype) { writer.WriteByte(Message.RawSubtype); } Message.Write(writer); writer.WriteDebugByte(42); var currentPos = (int)ms.Position; writer.WriteXORCheck(currentPos); uncompressedSize = (int)ms.Position; } } } var compress = (Message.SubtypeFlags & ClientMessageSubtypeFlag.Compress) == ClientMessageSubtypeFlag.Compress && uncompressedSize > 0; using (var writer = new ProtocolBufferWriter(bw, ProtocolBufferFlags.DontFragment)) { writer.WriteProtocolFlags(); writer.WritePacketType((ushort)Message.Type, compress); writer.WriteXORCheck((int)(bw.BaseStream.Position - packetBeginPosition)); } int packetSize = uncompressedSize; if (compress) // TODO: test { bw.Write((byte)0x01); bw.Write(uncompressedSize); var compressedBuffer = BufferManager.RequestBuffer(); int compressedSize; using (var compressStream = compressedBuffer.GetStream(true)) { using (var compressorStream = new DeflateStream(compressStream, CompressionMode.Compress, true)) compressorStream.Write(packetBuffer.Buffer, packetBuffer.BaseOffset, uncompressedSize); compressedSize = (int)compressStream.Position; } BufferManager.FreeBuffer(packetBuffer); packetBuffer = compressedBuffer; packetSize = compressedSize; } bw.Write(packetBuffer.Buffer, packetBuffer.BaseOffset, packetSize); BufferManager.FreeBuffer(packetBuffer); var currentPosition = bw.BaseStream.Position; bw.BaseStream.Position = sizePosition; bw.Write((ushort)(currentPosition - sizePosition)); bw.BaseStream.Position = currentPosition; }
public void RemoveSession(Session session) { _bufferManager.FreeBuffer(session.ReadEventArg); }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { //TimeSpan timeout = new TimeSpan(0, 0, 0, 5, 0); TimeSpan timeout = TimeSpan.FromMinutes(10); BufferManager bufferManager = new BufferManager(100 * 1024 * 2, 1024); bufferManager.InitBuffer(); while (!stoppingToken.IsCancellationRequested) { using TcpClient _tcpClient = new TcpClient(); AsyncUserToken asyncUserToken = new AsyncUserToken(); using SocketAsyncEventArgs sendArg = new SocketAsyncEventArgs(); using SocketAsyncEventArgs reciveArg = new SocketAsyncEventArgs(); reciveArg.Completed += new EventHandler <SocketAsyncEventArgs>(IO_Completed); reciveArg.UserToken = asyncUserToken; bufferManager.SetBuffer(reciveArg); try { _logger.LogInformation("连接"); await _tcpClient.ConnectAsync(hostname, port, stoppingToken); _logger.LogInformation("已连接"); NetworkStream ns = _tcpClient.GetStream(); asyncUserToken.Socket = _tcpClient.Client; for (int i = 0; i < 1000; i++) { try { DateTime startTime = DateTime.Now; if (_tcpClient.Connected == false) // 断线重连 { await _tcpClient.ConnectAsync(hostname, port); ns = _tcpClient.GetStream(); asyncUserToken.Socket = _tcpClient.Client; } #region write string msg = $"{Thread.CurrentThread.ManagedThreadId} >> {Guid.NewGuid():n} >> {DateTime.Now}"; _logger.LogInformation($"请求:\n\t{msg}\n"); byte[] requestBuffer = Encoding.UTF8.GetBytes(msg); sendArg.SetBuffer(requestBuffer); _tcpClient.Client.SendAsync(sendArg); #endregion #region read using CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken); cancellationTokenSource.CancelAfter(TimeSpan.FromSeconds(3)); using (cancellationTokenSource.Token.Register(() => _waitLock.Set())) { _waitLock.WaitOne(); } byte[] data = null; lock (asyncUserToken.Buffer) { data = asyncUserToken.Buffer.ToArray(); asyncUserToken.Buffer.Clear(); } if (data != null && data.Length > 0) { _logger.LogInformation($"响应:\n\t{Encoding.UTF8.GetString(data)}\n"); } #endregion _logger.LogInformation($"\n耗时: {DateTime.Now - startTime}\n"); // await Task.Delay(1000, stoppingToken); await Task.Delay(0, stoppingToken); //await Task.Delay(TimeSpan.FromMinutes(10)); } catch (Exception ex) { _logger.LogError(ex, ex.Message); await Task.Delay(5000, stoppingToken); } } } catch (TaskCanceledException) { } catch (Exception ex) { _logger.LogError(ex, ex.Message); } finally { bufferManager.FreeBuffer(reciveArg); _logger.LogInformation("断开连接"); _tcpClient?.Close(); _tcpClient?.Dispose(); _logger.LogInformation("已断开连接"); } await Task.Delay(2000, stoppingToken); } }
public void Send(string connectionId, byte[] buffer) { AsyncUserToken token; //SocketAsyncEventArgs token; //if (buffer.Length <= m_receiveSendBufferSize) //{ // throw new ArgumentException("数据包长度超过缓冲区大小", "buffer"); //} lock (((ICollection)this.m_tokens).SyncRoot) { if (!this.m_tokens.TryGetValue(connectionId, out token)) { throw new AsyncSocketException(string.Format("客户端:{0}已经关闭或者未连接", connectionId), AsyncSocketErrorCode.ClientSocketNoExist); //return; } } SocketAsyncEventArgs writeEventArgs; lock (m_writePool) { writeEventArgs = m_writePool.Pop();// 分配一个写SocketAsyncEventArgs对象 } writeEventArgs.UserToken = token; if (buffer.Length <= m_BufferSize) { Array.Copy(buffer, 0, writeEventArgs.Buffer, writeEventArgs.Offset, buffer.Length); writeEventArgs.SetBuffer(writeEventArgs.Buffer, writeEventArgs.Offset, buffer.Length); } else { lock (m_bufferLock) { m_bufferManager.FreeBuffer(writeEventArgs); } writeEventArgs.SetBuffer(buffer, 0, buffer.Length); } //writeEventArgs.SetBuffer(buffer, 0, buffer.Length); try { // 异步发送数据 bool willRaiseEvent = token.Socket.SendAsync(writeEventArgs); if (!willRaiseEvent) { ProcessSend(writeEventArgs); } } catch (ObjectDisposedException) { RaiseDisconnectedEvent(token); } catch (SocketException socketException) { if (socketException.ErrorCode == (int)SocketError.ConnectionReset) //10054一个建立的连接被远程主机强行关闭 { RaiseDisconnectedEvent(token); //引发断开连接事件 } else { RaiseErrorEvent(token, new AsyncSocketException("在SocketAsyncEventArgs对象上执行异步发送数据操作时发生SocketException异常", socketException));; } } catch (Exception exception_debug) { Debug.WriteLine("调试:" + exception_debug.Message); throw exception_debug; } }
private void Clear(BufferManager buffermanager) { buffermanager.FreeBuffer(_ReadAsyncEventArgs); }