原创

netty入门教程-netty使用ProtoBuf

1. 介绍

2.服务端代码

pom.xml

<dependencies>

        <!-- https://mvnrepository.com/artifact/com.google.inject/guice -->
        <dependency>
            <groupId>com.google.inject</groupId>
            <artifactId>guice</artifactId>
            <version>4.2.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java -->
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.9.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.37.Final</version>
        </dependency>

    </dependencies>

1.服务端启动类,已经初始化类

GerantSocketServer.java

package com.fireflyi.gn.gerant.service;

import com.fireflyi.gn.gerant.common.protobuf.GerantReqProtobuf;
import com.fireflyi.gn.gerant.service.core.GerantServerInitializer;
import com.fireflyi.gn.gerant.service.handle.GerantServerHandle;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;

/**
 * @author by fireflyi (6025606@qq.com)
 * @website https://www.fireflyi.com
 * @date 2019/7/20
 * DESC TODO
 */
public class GerantSocketServer {

    private static final Integer PORT = 6288;

    public static void main(String[] args){
        EventLoopGroup boosGroup = new NioEventLoopGroup();
        EventLoopGroup workGroup = new NioEventLoopGroup();
        try{
            ServerBootstrap b = new ServerBootstrap();
            b.group(boosGroup, workGroup);
            b.channel(NioServerSocketChannel.class);
            b.childHandler(new ChannelInitializer<Channel>() {  //通道是NioSocketChannel
                @Override
                protected void initChannel(Channel ch) throws Exception {
                    //字符串编码器,一定要加在GerantServerHandle 的上面
                    ch.pipeline()
                            .addLast(new ProtobufVarint32FrameDecoder())
                            .addLast(new ProtobufDecoder(GerantReqProtobuf.GerantReqProtocol.getDefaultInstance()))
                            .addLast(new ProtobufVarint32LengthFieldPrepender())
                            .addLast(new ProtobufEncoder())
                            //找到他的管道 增加他的handler
                            .addLast(new GerantServerHandle());
                }
            });
            System.out.println("服务端等待客户端连接...");
            // 绑定端口,同步等待成功
            Channel ch = b.bind(PORT).sync().channel();

            // 等待服务端监听端口关闭
            ch.closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //优雅的退出程序
            boosGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }

}

2.服务端业务处理Handle

GerantServerHandle

package com.fireflyi.gn.gerant.service.handle;

import com.fireflyi.gn.gerant.common.protobuf.GerantReqProtobuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

/**
 * @author by fireflyi (6025606@qq.com)
 * @website https://www.fireflyi.com
 * @date 2019/7/18
 * DESC TODO
 */

@ChannelHandler.Sharable
public class GerantServerHandle extends SimpleChannelInboundHandler<GerantReqProtobuf.GerantReqProtocol> {

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, GerantReqProtobuf.GerantReqProtocol msg) throws Exception {
        System.out.println("收到"+ msg.getReqMsg()+",Type->"+msg.getType().getNumber());
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("有新链接");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //异常时断开连接
        System.out.println(333);
        cause.printStackTrace() ;
        ctx.close() ;
    }
}

2.客户端代码

1.客户端启动类和初始化类

GerantSocketclient.java

package com.fireflyi.gn.gerant.service;

import com.fireflyi.gn.gerant.common.protobuf.GerantReqProtobuf;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;

/**
 * @author by fireflyi (6025606@qq.com)
 * @website https://www.fireflyi.com
 * @date 2019/7/20
 * DESC TODO
 */
public class GerantSocketclient {

    private static final Integer PORT = 6088;

    public static void main(String[] args){

        // 首先,netty通过ServerBootstrap启动服务端
        Bootstrap client = new Bootstrap();

        EventLoopGroup group = new NioEventLoopGroup();
        try{
            client.group(group);
            client.channel(NioSocketChannel.class);
            client.handler(new ChannelInitializer<Channel>() {  //通道是NioSocketChannel
                @Override
                protected void initChannel(Channel ch) throws Exception {
                    //字符串编码器,一定要加在SimpleClientHandler 的上面
                    ch.pipeline()
                            .addLast(new ProtobufVarint32FrameDecoder())
                            .addLast(new ProtobufDecoder(GerantReqProtobuf.GerantReqProtocol.getDefaultInstance()))
                            .addLast(new ProtobufVarint32LengthFieldPrepender())
                            .addLast(new ProtobufEncoder())
                    //找到他的管道 增加他的handler
                            .addLast(new SimpleClientHandler());
                }
            });

            // 发起异步连接服务器
            ChannelFuture future = client.connect("127.0.0.1", PORT).sync();
            if(future.isSuccess()){
                System.out.println("客户端链接成功");
            }
            //发送Protobuf数据
            GerantReqProtobuf.GerantReqProtocol.Builder builder = GerantReqProtobuf.GerantReqProtocol.newBuilder();
            builder.setType(GerantReqProtobuf.ChatType.CHAT_TYPE_PUBLIC);
            builder.setReqMsg("cliend,send protobuf消息");

            ChannelFuture futures = future.channel().writeAndFlush(builder.build());
            futures.addListener((ChannelFutureListener) channelFuture ->
                    System.out.println("客户端手动发消息成功"));

            //
            future.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //优雅的退出程序
            group.shutdownGracefully();
        }
    }

}

2.客户端业务处理Handle

SimpleClientHandler.java

package com.fireflyi.gn.gerant.service;

import com.fireflyi.gn.gerant.common.protobuf.GerantReqProtobuf;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.AttributeKey;

import java.nio.charset.Charset;

/**
 * @author by fireflyi (6025606@qq.com)
 * @website https://www.fireflyi.com
 * @date 2019/7/20
 * DESC TODO
 */
@ChannelHandler.Sharable
public class SimpleClientHandler extends SimpleChannelInboundHandler<GerantReqProtobuf.GerantReqProtocol> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, GerantReqProtobuf.GerantReqProtocol msg) throws Exception {
        System.out.println("收到服务端消息"+msg.toString());
    }

}

3.测试结果

"服务端"
服务端等待客户端连接...
有新链接
收到cliend,send protobuf消息,Type->0

"客户端"
客户端链接成功
客户端手动发消息成功
正文到此结束
本文目录