Netty--Google Protobuf編解碼

Google Protobuf是一種輕便高效的結構化數據存儲格式,能夠用於結構化數據序列化。它很適合作數據存儲或 RPC 數據交換格式。可用於通信協議、數據存儲等領域的語言無關、平臺無關、可擴展的序列化結構數據格式。java

 

編譯安裝:git

下載Java版 https://github.com/google/protobuf/releasesgithub

tar -zxvf xxx.tar.gzbootstrap

./configure數組

makeide

make installoop

protoc --version測試

mvn installui

mvn packagegoogle

 

使用:

Google Protobuf支持複雜的POJO對象的編解碼,而這些代碼是自動生成的。

首先寫文件Person.proto ,定義程序中須要處理的結構化數據,在 protobuf 的中,結構化數據被稱爲 Message。

syntax="proto3"; 
package com.luangeng.netty.protobuf; 

message Person { 
string username=1; //
int32 age=2; //
string sex=3; //
}

 

執行命令

protoc -I=. --java_out=. Person.proto

格式: protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/***.proto

 

即在當前目錄下生成了Java文件PersonOutClass.java, 將它引入到工程並須要添加POM依賴

<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>3.5.0</version>
</dependency>

--

 

而後作一個簡單的編解碼測試:

public class TestProtoBuf {

    //編碼爲byte數組
    private static byte[] encoder(PersonOuterClass.Person p) {
        return p.toByteArray();
    }

    //從byte數組解碼
    private static PersonOuterClass.Person decoder(byte[] b) throws InvalidProtocolBufferException {
        return PersonOuterClass.Person.parseFrom(b);
    }

    //使用builder實例來設置屬性
    private static PersonOuterClass.Person create(){
        PersonOuterClass.Person.Builder builder = PersonOuterClass.Person.newBuilder();
        builder.setAge(10);
        builder.setSex("man");
        builder.setUsername("luangeng");
        return builder.build();
    }

    public static void main(String[] args) throws InvalidProtocolBufferException {
        PersonOuterClass.Person p = create();
        Q.p("before----------\n" + p.toString());

        PersonOuterClass.Person p2 = decoder(encoder(p));
        Q.p("afetr-----------\n" + p2.toString());
    }

}

---

輸出結果:

before----------
username: "luangeng"
age: 10
sex: "man"

afetr-----------
username: "luangeng"
age: 10
sex: "man"

 

 

在Netty中使用Google Protobuf實例:

Server端:

public class EchoServer {
    public static void main(String[] args) {
        new EchoServer().bind(8080);
    }

    public void bind(int port) {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 100)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new ProtobufVarint32FrameDecoder());
                            ch.pipeline().addLast(new ProtobufDecoder(PersonOuterClass.Person.getDefaultInstance()));
                            ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
                            ch.pipeline().addLast(new ProtobufEncoder());
                            ch.pipeline().addLast(new EchoServerHandler());
                        }
                    });
            ChannelFuture future = bootstrap.bind(port).sync();
            System.out.println("server started");
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("server shuting down");
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

public class EchoServerHandler extends ChannelInboundHandlerAdapter {
    int count = 0;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        PersonOuterClass.Person p = (PersonOuterClass.Person) msg;
        System.out.println("Server received " + count++ + " :\n" + p.toString());
        ctx.writeAndFlush(msg);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

---

 

Client端:

public class EchoClient {

    public static void main(String[] args) {
        new EchoClient().connect("127.0.0.1", 8080);
    }

    public void connect(String host, int port) {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group).channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new ProtobufVarint32FrameDecoder());
                            ch.pipeline().addLast(new ProtobufDecoder(PersonOuterClass.Person.getDefaultInstance()));
                            ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
                            ch.pipeline().addLast(new ProtobufEncoder());
                            ch.pipeline().addLast(new EchoClientHandler());
                        }
                    });
            ChannelFuture future = bootstrap.connect(host, port).sync();
            System.out.println("client started");
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("client shuting down");
            group.shutdownGracefully();
        }
    }
}

public class EchoClientHandler extends ChannelInboundHandlerAdapter {

    private int count = 0;

    private static PersonOuterClass.Person create(int i) {
        PersonOuterClass.Person.Builder builder = PersonOuterClass.Person.newBuilder();
        builder.setAge(i);
        builder.setSex("man");
        builder.setUsername("luangeng" + i);
        return builder.build();
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        for (int i = 0; i < 20; i++) {
            ctx.writeAndFlush(create(i));
        }
    }

    //服務端返回應答信息後調用
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        PersonOuterClass.Person p = (PersonOuterClass.Person) msg;
        Q.p("Client get " + count++ + " :\n" + p.toString());
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

---

執行結果:

client started
Client get 0 :
username: "luangeng0"
sex: "man"

Client get 1 :
username: "luangeng1"
age: 1
sex: "man"

Client get 2 :
username: "luangeng2"
age: 2
sex: "man"

Client get 3 :
username: "luangeng3"
age: 3
sex: "man"

Client get 4 :
username: "luangeng4"
age: 4
sex: "man"

Client get 5 :
username: "luangeng5"
age: 5
sex: "man"

Client get 6 :
username: "luangeng6"
age: 6
sex: "man"

Client get 7 :
username: "luangeng7"
age: 7
sex: "man"

Client get 8 :
username: "luangeng8"
age: 8
sex: "man"

Client get 9 :
username: "luangeng9"
age: 9
sex: "man"

Client get 10 :
username: "luangeng10"
age: 10
sex: "man"

Client get 11 :
username: "luangeng11"
age: 11
sex: "man"

Client get 12 :
username: "luangeng12"
age: 12
sex: "man"

Client get 13 :
username: "luangeng13"
age: 13
sex: "man"

Client get 14 :
username: "luangeng14"
age: 14
sex: "man"

Client get 15 :
username: "luangeng15"
age: 15
sex: "man"

 

end

相關文章
相關標籤/搜索