Example #1
0
        private uint GetHeader(IByteBuffer content)
        {
            var header = content.ReadByte();

            content.DiscardReadBytes();
            return(header);
        }
Example #2
0
        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();
        }
Example #5
0
        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();
                }
            }
        }
Example #6
0
 public virtual IByteBuffer DiscardReadBytes()
 {
     _ = Buf.DiscardReadBytes();
     return(this);
 }
Example #7
0
    //패킷 완성후, 다음 데이터가 없는지 체크하는 함수.
    //패킷 완성후, 다시 자기자신을 호출하여 다음 데이터가 없을때까지 계속 자기자신을 호출한다.
    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);
        }
    }