private uint GetHeader(IByteBuffer content) { var header = content.ReadByte(); content.DiscardReadBytes(); return(header); }
public List <Message> AddAndGetMessage(IByteBuffer byteBuf) { List <Message> list = new List <Message>(); if (cumulationBuff == null) { cumulationBuff = byteBuf; } else { cumulationBuff.WriteBytes(byteBuf.ReadeBytes()); } bool isParse = true; while (isParse) { isParse = false; if (Status == 0 && cumulationBuff.ReadableBytes >= HEADER_LENGTH)//解析head { bodyLength = cumulationBuff.GetInt(cumulationBuff.ReaderIndex + 4); Status = 1; if (bodyLength > cumulationBuff.MaxCapacity) { throw new Exception("包长超过最大值"); } } if (Status == 1 && cumulationBuff.ReadableBytes >= bodyLength + HEADER_LENGTH) //解析body { byte[] frameData = cumulationBuff.ReadeBytes(cumulationBuff.ReaderIndex, bodyLength + HEADER_LENGTH); Status = 0; list.Add(Decode(frameData)); isParse = true; } }//while if (list.Count > 0) { if (cumulationBuff != null && !cumulationBuff.IsReadable()) { cumulationBuff = null; } else { cumulationBuff.DiscardReadBytes(); } } return(list); }
public static void MakeSpace(this IByteBuffer output, int length, string reason = null) { if (output.WritableBytes < length) { if (output.ReaderIndex == output.WriterIndex) { output.Clear(); } else { output.DiscardReadBytes(); } if (output.WritableBytes < length) { output.EnsureWritable(length, true); } } }
public void DiscardReadBytes3() { IByteBuffer a = Unpooled.WrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); IByteBuffer b = Unpooled.WrappedBuffer( Unpooled.WrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 0, 5), Unpooled.WrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 5, 5)); a.SkipBytes(6); a.MarkReaderIndex(); b.SkipBytes(6); b.MarkReaderIndex(); Assert.Equal(a.ReaderIndex, b.ReaderIndex); a.SetReaderIndex(a.ReaderIndex - 1); b.SetReaderIndex(b.ReaderIndex - 1); Assert.Equal(a.ReaderIndex, b.ReaderIndex); a.SetWriterIndex(a.WriterIndex - 1); a.MarkWriterIndex(); b.SetWriterIndex(b.WriterIndex - 1); b.MarkWriterIndex(); Assert.Equal(a.WriterIndex, b.WriterIndex); a.SetWriterIndex(a.WriterIndex + 1); b.SetWriterIndex(b.WriterIndex + 1); Assert.Equal(a.WriterIndex, b.WriterIndex); Assert.True(ByteBufferUtil.Equals(a, b)); // now discard a.DiscardReadBytes(); b.DiscardReadBytes(); Assert.Equal(a.ReaderIndex, b.ReaderIndex); Assert.Equal(a.WriterIndex, b.WriterIndex); Assert.True(ByteBufferUtil.Equals(a, b)); a.ResetReaderIndex(); b.ResetReaderIndex(); Assert.Equal(a.ReaderIndex, b.ReaderIndex); a.ResetWriterIndex(); b.ResetWriterIndex(); Assert.Equal(a.WriterIndex, b.WriterIndex); Assert.True(ByteBufferUtil.Equals(a, b)); a.Release(); b.Release(); }
private IByteBuffer cumulationBuff = null; //这里可以优化为组合buff 就完全实现了零拷贝了 public override void ChannelRead(IChannelHandlerContext context, object message) { IByteBuffer byteBuf = message as IByteBuffer; if (byteBuf == null) { context.FireChannelRead(message); return; } if (cumulationBuff == null) { cumulationBuff = byteBuf; } else { cumulationBuff.WriteBytes(byteBuf.ReadeBytes()); //如果这里是组合buff,可以提高cpu性能了 } var output = new List <object>(); this.Decode(context, cumulationBuff, output); foreach (var item in output) { context.FireChannelRead(item); //把数据交给下一个handler } if (output.Count > 0) { if (cumulationBuff != null && !cumulationBuff.IsReadable()) { cumulationBuff = null; } else { cumulationBuff.DiscardReadBytes(); } } }
public virtual IByteBuffer DiscardReadBytes() { _ = Buf.DiscardReadBytes(); return(this); }
//패킷 완성후, 다음 데이터가 없는지 체크하는 함수. //패킷 완성후, 다시 자기자신을 호출하여 다음 데이터가 없을때까지 계속 자기자신을 호출한다. bool isCompleteSizePacket(int packet_size, IChannelHandlerContext ctx, IByteBuffer msg) { //아직 버퍼에 데이터가 충분하지 않다면 다시 되돌려서 패킷을 이어서 더 받아오게끔 하는 부분! if (msg.ReadableBytes < packet_size + 8) { //정상적으로 데이터를 다 읽은것이 아니므로 아까 MarkReaderIndex로 저장했던 0값으로 readerIndex 4 -> 0로 초기화함. msg.ResetReaderIndex(); return(false); //다시 되돌려서 패킷을 이어서 더 받아오게끔 하는 부분! } //패킷이 뭉쳐서 데이터를 더 받아왔을 경우! 원래 받아야 할 부분만 받고, 나머지는 다시 되돌려서 뒤이어 오는 패킷과 합쳐서 받을 것! else if (msg.ReadableBytes > packet_size + 8) { //받아온 데이터. byte[] packet_data = new byte[msg.ReadableBytes]; msg.ReadBytes(packet_data, 0, msg.ReadableBytes); //버퍼의 현재 용량에서 추가로 기록가능한 영역이 10KB 이하라면, //이미 읽은 분량만큼은 필요없으므로 Index 0의 위치로 데이터를 옮겨 추가로 기록가능한 영역을 늘린다. if (msg.Capacity - msg.WriterIndex < 10000) { msg.DiscardReadBytes(); } //받아온 데이터를 메인스레드와 통신하기 위한 목적으로 만들어둔 수신 Queue에 삽입. //멀티스레드에서 공유하는 Queue이므로, Locking 처리. NetworkManager.locking 는 스레드 lock용 모니터 객체이다. lock (NetworkManager.locking) { //받아온 데이터를 수신Queue에 삽입하는 부분. //데이터 삽입. NetworkManager.packet_Queue.Enqueue(new Packet_Data(packet_data)); } //패킷 완성후 남은 데이터가 헤더크기인 12byte보다 작을 경우. if (msg.ReadableBytes < 12) { return(false); } else { msg.MarkReaderIndex(); int amountSize = msg.ReadIntLE(); //비정상적인 데이터가 도달하였다면. if (!isAvailablePacketSize(amountSize)) { //연결 종료 ctx.CloseAsync(); //채널이 닫힌다면 msg는 release 된다. return(false); } return(isCompleteSizePacket(amountSize, ctx, msg)); //재귀함수 처리 //패킷 완성후, 남은데이터가 없을때까지 계속 반복한다. } } else //정확한 데이터일 경우. [msg.ReadableBytes > packet_size + 8] 또는 [msg.readableBytes() + 4 == packet_size + 12] { //받아온 데이터. byte[] packet_data = new byte[msg.ReadableBytes]; msg.ReadBytes(packet_data, 0, msg.ReadableBytes); //버퍼에 읽어와야 할 데이터가 남아있지 않으므로 readerIndex, writerIndex를 각각 0으로 초기화 한다. //내부 버퍼 데이터를 변경하지 않고 index값만 변경하므로 자원을 적게 소모한다. msg.Clear(); //받아온 데이터를 메인스레드와 통신하기 위한 목적으로 만들어둔 수신 Queue에 삽입. //멀티스레드에서 공유하는 Queue이므로, Locking 처리. NetworkManager.locking 는 스레드 lock용 모니터 객체이다. lock (NetworkManager.locking) { //받아온 데이터를 수신Queue에 삽입하는 부분. //데이터 삽입. NetworkManager.packet_Queue.Enqueue(new Packet_Data(packet_data)); } //다시 되돌려서 패킷을 이어서 더 받아오게끔 하는 부분! return(false); } }