1. 安装开发环境

1.1 Netty环境
  这里我使用Netty5.0.0版本 到这里下载即可http://netty.io/ 下载netty-all-5.0.0.Alpha2.jar 这个jar包简单配置一下即可使用。
1.2 Protobuf环境
  这个就比较麻烦了,这里说一下我的做法。 可以在这里下载最新版https://github.com/google/protobuf 或者使用 v2.6.1稳定版 https://github.com/google/protobuf/tree/v2.6.1
  也可以在这里下载http://pkgs.fedoraproject.org/repo/pkgs/protobuf/protobuf-2.6.1.tar.bz2/
  在这里下载对应的Protobuf-java.jar http://central.maven.org/maven2/com/google/protobuf/protobuf-java/
  http://mvnrepository.com/artifact/com.google.protobuf/protobuf-java

1.3 Protoc 工具
  Linux和Windows都差不多,编译源代码即可。
  以Windows为例,打开\protobuf-2.6.1\vsprojects\protobuf.sln
Netty5 + Protobuf 使用
  这样生成解决方案。
Netty5 + Protobuf 使用
  在Debug里面这些文件是有用的

Netty5 + Protobuf 使用

2. protobuf初始化

SubscribeReq.proto

 1 package netty;
 2 option java_package = "com.jieli.nettytest.protobuf";
 3 option java_outer_classname = "SubscribeReqProto";
 4 
 5 message SubscribeReq{
 6     required int32 subReqID = 1;
 7     required string userName = 2;
 8     required string productName = 3;
 9     repeated string address = 4;
10 }

SubscribeResq.proto

1 package netty;
2 option java_package = "com.jieli.nettytest.protobuf";
3 option java_outer_classname = "SubscribeResqProto";
4 
5 message SubscribeResq{
6     required int32 subReqID = 1;
7     required int32 respCode = 2;
8     required string desc = 3;
9 }

  用protobuf.exe进行编译

1 protoc.exe --java_out=. --cpp_out=. SubscribeReq.proto
2 protoc.exe --java_out=. --cpp_out=. SubscribeResq.proto

3. Protobuf 测试

  TestSubscribeReqProto.java

 1 package com.jieli.nettytest.protobuf;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 import com.google.protobuf.InvalidProtocolBufferException;
 6 
 7 public class TestSubscribeReqProto {
 8     
 9     private static byte[] encode(SubscribeReqProto.SubscribeReq req){
10         return req.toByteArray();
11     }
12     
13     private static SubscribeReqProto.SubscribeReq decode(byte[] body) 
14             throws InvalidProtocolBufferException {
15         return SubscribeReqProto.SubscribeReq.parseFrom(body);
16     }
17     
18     private static SubscribeReqProto.SubscribeReq createSubscribeReq(){
19         SubscribeReqProto.SubscribeReq.Builder builder = 
20                 SubscribeReqProto.SubscribeReq.newBuilder();
21         builder.setSubReqID(1);
22         builder.setUserName("Lilinfeng");
23         builder.setProductName("netty book");
24         List<String> address = new ArrayList<>();
25         address.add("NanJing YuHuaTai");
26         address.add("beijin lilili");
27         address.add("asdfasdf");
28         builder.addAllAddress(address);
29         return builder.build();
30     }
31     
32     public static void main(String[] args) {
33         try {
34             SubscribeReqProto.SubscribeReq req = createSubscribeReq();
35             System.out.println("befor encode:" + req.toString());
36             SubscribeReqProto.SubscribeReq req2 = decode(encode(req));
37             System.out.println("After decode :"+req.toString());
38             System.out.println("assert equal : ==>" + req2.equals(req));
39         } catch (Exception e) {
40             e.printStackTrace();
41         }
42     }
43 }

  运行结果

Netty5 + Protobuf 使用

  项目目录结构

Netty5 + Protobuf 使用

4. java-java通信例子(跟书本上是差不多一样的)

  SubReqServer.java

 1 package com.jieli.nettytest.protobuf;
 2 
 3 import io.netty.bootstrap.ServerBootstrap;
 4 import io.netty.channel.ChannelFuture;
 5 import io.netty.channel.ChannelInitializer;
 6 import io.netty.channel.ChannelOption;
 7 import io.netty.channel.EventLoopGroup;
 8 import io.netty.channel.nio.NioEventLoopGroup;
 9 import io.netty.channel.socket.SocketChannel;
10 import io.netty.channel.socket.nio.NioServerSocketChannel;
11 import io.netty.handler.codec.protobuf.ProtobufDecoder;
12 import io.netty.handler.codec.protobuf.ProtobufEncoder;
13 import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
14 import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
15 import io.netty.handler.logging.LogLevel;
16 import io.netty.handler.logging.LoggingHandler;
17 
18 public class SubReqServer {
19     
20     public void bind(int port){
21         EventLoopGroup bossGroup = new NioEventLoopGroup();
22         EventLoopGroup workerGroup = new NioEventLoopGroup();
23         try {
24             ServerBootstrap b = new ServerBootstrap();
25             b.group(bossGroup, workerGroup)
26              .channel(NioServerSocketChannel.class)
27              .option(ChannelOption.SO_BACKLOG, 100)
28              .handler(new LoggingHandler(LogLevel.INFO))
29              .childHandler(new ChannelInitializer<SocketChannel>() {
30                 @Override
31                 protected void initChannel(SocketChannel ch) throws Exception {
32                     ch.pipeline().addLast(new ProtobufVarint32FrameDecoder()); 
33                     //与c++通信时这里的varint32要注释掉,因为默认的protobuf是没有32位对齐的,如果要实现自动分包,那么要在C++客户端进行组装
34                     ch.pipeline().addLast(new ProtobufDecoder(
35                             SubscribeReqProto.SubscribeReq.getDefaultInstance()));
36                     ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
37                     ch.pipeline().addLast(new ProtobufEncoder());
38                     ch.pipeline().addLast(new SubReqServerHandler());
39                 }
40             });
41             
42             ChannelFuture f = b.bind(port).sync();
43             
44             f.channel().closeFuture().sync();
45         } catch (Exception e) {
46             e.printStackTrace();
47         } finally {
48             bossGroup.shutdownGracefully();
49             workerGroup.shutdownGracefully();
50         }
51     }
52     
53     public static void main(String[] args) {
54         new SubReqServer().bind(7777);
55     }
56 }
View Code

相关文章: