netty 自定义协议


netty 自定义协议

        

               

                                  

自定义协议

        

Message

@Data
public class Message {

    private int magic;       //魔数
    private int version;     //消息版本
    private byte classType;  //类:0表示Person、1表示Product
    private int length;      //消息体的长度
    private byte[] body;     //消息体内容
}

         

ClassType

public class ClassType {

    public static Map<Byte,Class<?>> getType(){
        Map<Byte, Class<?>> type = new HashMap<>();
        type.put((byte)0, Person.class);
        type.put((byte)1, Product.class);

        return type;
    }
}

         

Person

@Data
public class Person {

    private String name;
    private Integer age;
}

         

Product

@Data
public class Product {

    private String name;
    private Float price;
    private Integer num;
}

          

                                  

自定义编解码器

   

CustomMessageEncoder

public class CustomMessageEncoder extends MessageToByteEncoder<Message> {

    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, Message message, ByteBuf byteBuf) throws Exception {
        byteBuf.writeInt(message.getMagic());
        byteBuf.writeInt(message.getVersion());
        byteBuf.writeByte(message.getClassType());
        byteBuf.writeInt(message.getLength());
        byteBuf.writeBytes(message.getBody());
    }
}

        

CustomMessageDecoder

public class CustomMessageDecoder extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        Message message = new Message();

        int magic = byteBuf.readInt();
        if (magic != 100000){
            channelHandlerContext.channel().close();
            return;
        }

        int version = byteBuf.readInt();
        byte classType = byteBuf.readByte();

        int length = byteBuf.readInt();
        byte[] body = new byte[length];
        byteBuf.readBytes(body);

        message.setMagic(magic);
        message.setVersion(version);
        message.setClassType(classType);
        message.setLength(length);
        message.setBody(body);
        list.add(message);

        switch (classType){
            case 0:{
                System.out.println("服务端接收到person数据");
                Person person = JSON.parseObject(body, ClassType.getType().get((byte)0));
                System.out.println(person);
            } break;

            case 1:{
                System.out.println("服务端接收到product数据");
                Product product = JSON.parseObject(body, Product.class);
                System.out.println(product);
            }
        }
    }
}

             

            

                                  

服务端

  

CustomServerHandler

public class CustomServerHandler extends SimpleChannelInboundHandler<Message> {

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Message message) throws Exception {
        System.out.println("服务端接收到的message对象为:"+message);
    }
}

       

NettyServer

public class NettyServer {

    public static void startServer(int port){
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline channelPipeline = socketChannel.pipeline();
                            channelPipeline.addLast(new CustomMessageDecoder());
                            channelPipeline.addLast(new CustomServerHandler());
                        }
                    });

            ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
            channelFuture.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        startServer(8000);
    }
}

       

             

                                  

客户端

       

CustomClientHandler

public class CustomClientHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("客户端开始发送person数据");
        Message message = new Message();
        message.setMagic(100000);
        message.setVersion(1);
        message.setClassType((byte)0);

        Person person = new Person();
        person.setName("瓜田李下");
        person.setAge(20);
        byte[] bytes = JSON.toJSONBytes(person);
        message.setLength(bytes.length);
        message.setBody(bytes);

        ctx.channel().writeAndFlush(message);

        System.out.println("客户端开始发送product数据");
        Message message2 = new Message();
        message2.setMagic(100000);
        message2.setVersion(1);
        message2.setClassType((byte)1);

        Product product = new Product();
        product.setName("苹果");
        product.setPrice(4f);
        product.setNum(100);
        byte[] bytes2 = JSON.toJSONBytes(product);
        message2.setLength(bytes2.length);
        message2.setBody(bytes2);

        ctx.channel().writeAndFlush(message2);
    }
}

             

NettyClient

public class NettyClient {

    public static void connect(String host, int port){
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .handler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline channelPipeline = socketChannel.pipeline();
                            channelPipeline.addLast(new CustomMessageEncoder());
                            channelPipeline.addLast(new CustomClientHandler());
                        }
                    });
            ChannelFuture channelFuture = bootstrap.connect(host,port).sync();
            channelFuture.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            eventLoopGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        String host = "localhost";
        int port = 8000;
        connect(host, port);
    }
}

         

             

                                  

使用测试

       

点击运行后,服务端输出:

08:51:09.785 [nioEventLoopGroup-3-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.ratio: 8
08:51:09.785 [nioEventLoopGroup-3-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.chunkSize: 32
08:51:09.785 [nioEventLoopGroup-3-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.blocking: false
08:51:09.803 [nioEventLoopGroup-3-1] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkAccessible: true
08:51:09.803 [nioEventLoopGroup-3-1] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkBounds: true
08:51:09.808 [nioEventLoopGroup-3-1] DEBUG io.netty.util.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@63ce0f70
服务端接收到person数据
Person(name=瓜田李下, age=20)
服务端接收到的message对象为:Message(magic=100000, version=1, classType=0, length=32, body=[123, 34, 97, 103, 101, 34, 58, 50, 48, 44, 34, 110, 97, 109, 101, 34, 58, 34, -25, -109, -100, -25, -108, -80, -26, -99, -114, -28, -72, -117, 34, 125])
服务端接收到product数据
Product(name=苹果, price=4.0, num=100)
服务端接收到的message对象为:Message(magic=100000, version=1, classType=1, length=39, body=[123, 34, 110, 97, 109, 101, 34, 58, 34, -24, -117, -71, -26, -98, -100, 34, 44, 34, 110, 117, 109, 34, 58, 49, 48, 48, 44, 34, 112, 114, 105, 99, 101, 34, 58, 52, 46, 48, 125])

          

点击运行后,客户端输出:

08:51:09.352 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.cacheTrimIntervalMillis: 0
08:51:09.352 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.useCacheForAllThreads: false
08:51:09.353 [main] DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxCachedByteBuffersPerChunk: 1023
08:51:09.380 [main] DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.allocator.type: pooled
08:51:09.380 [main] DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.threadLocalDirectBufferSize: 0
08:51:09.381 [main] DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.maxThreadLocalCharBufferSize: 16384
客户端开始发送person数据
08:51:09.743 [nioEventLoopGroup-2-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxCapacityPerThread: 4096
08:51:09.744 [nioEventLoopGroup-2-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.ratio: 8
08:51:09.744 [nioEventLoopGroup-2-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.chunkSize: 32
08:51:09.744 [nioEventLoopGroup-2-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.blocking: false
08:51:09.758 [nioEventLoopGroup-2-1] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkAccessible: true
08:51:09.762 [nioEventLoopGroup-2-1] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkBounds: true
08:51:09.765 [nioEventLoopGroup-2-1] DEBUG io.netty.util.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@6ed2763b
客户端开始发送product数据

         

                   

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个简单的Netty自定义协议的示例代码,该协议由消息头和消息体组成,消息头包含消息的长度信息,消息体包含具体的消息内容。 1. 定义消息类 ```java public class MyMessage { private int length; private String content; // getter and setter methods } ``` 2. 编写编解码器 ```java public class MyMessageCodec extends MessageToByteEncoder<MyMessage> { @Override protected void encode(ChannelHandlerContext ctx, MyMessage msg, ByteBuf out) throws Exception { byte[] contentBytes = msg.getContent().getBytes(CharsetUtil.UTF_8); out.writeInt(contentBytes.length); out.writeBytes(contentBytes); } } public class MyMessageDecoder extends ByteToMessageDecoder { @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { if (in.readableBytes() < 4) { return; } in.markReaderIndex(); int length = in.readInt(); if (in.readableBytes() < length) { in.resetReaderIndex(); return; } byte[] contentBytes = new byte[length]; in.readBytes(contentBytes); String content = new String(contentBytes, CharsetUtil.UTF_8); MyMessage message = new MyMessage(); message.setLength(length); message.setContent(content); out.add(message); } } ``` 3. 编写服务端和客户端代码 服务端代码: ```java public class MyServer { public static void main(String[] args) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new MyMessageDecoder()); pipeline.addLast(new MyServerHandler()); pipeline.addLast(new MyMessageCodec()); } }) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); ChannelFuture f = b.bind(8888).sync(); f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } } public class MyServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { MyMessage message = (MyMessage) msg; System.out.println("Server receive message: " + message.getContent()); message.setContent("Hello, " + message.getContent() + "!"); ctx.writeAndFlush(message); } } ``` 客户端代码: ```java public class MyClient { public static void main(String[] args) throws Exception { EventLoopGroup workerGroup = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(workerGroup) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new MyMessageCodec()); pipeline.addLast(new MyMessageDecoder()); pipeline.addLast(new MyClientHandler()); } }); ChannelFuture f = b.connect("localhost", 8888).sync(); for (int i = 0; i < 10; i++) { MyMessage message = new MyMessage(); message.setContent("world-" + i); f.channel().writeAndFlush(message); Thread.sleep(1000); } f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); } } } public class MyClientHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { MyMessage message = (MyMessage) msg; System.out.println("Client receive message: " + message.getContent()); } } ``` 以上代码演示了如何使用Netty实现自定义协议,其中MyMessageCodec和MyMessageDecoder负责编解码,MyServer和MyServerHandler负责服务端逻辑,MyClient和MyClientHandler负责客户端逻辑。在本示例中,自定义协议包含消息头和消息体,消息头包含消息长度信息,消息体包含具体的消息内容。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值