版本:java7 netty5 protobuf-java-2.5.0
protobuf 消息定义如下:
Auth.proto
option java_package = "com.xinli.netty.protobuf"; package auth; message AuthRequest{ // (1) required string user_id=1; required string password=2; } message AuthResponse{ //(2) required int32 result_code=1; required string result_message=2; }
说明:
(1)请求消息,包括用户ID和密码
(2)应答消息,包括响应码和响应说明
服务端:
Auth.java(Auth.proto编译后的java文件) AuthServer.java AuthServerInitHandler.java
AuthServer.java
package com.xinli.netty.protobuf; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.LengthFieldBasedFrameDecoder; import io.netty.handler.codec.LengthFieldPrepender; import io.netty.handler.codec.protobuf.ProtobufDecoder; import io.netty.handler.codec.protobuf.ProtobufEncoder; import java.util.logging.Level; import java.util.logging.Logger; public class AuthServer { private static Logger logger = Logger.getLogger(AuthServerInitHandler.class .getName()); public void start(int port) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup();// (1) EventLoopGroup workerGroup = new NioEventLoopGroup();// (2) try { ServerBootstrap b = new ServerBootstrap();// (3) b.group(bossGroup, workerGroup); // (4) b.channel(NioServerSocketChannel.class); b.childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { //decoded ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4)); ch.pipeline().addLast(new ProtobufDecoder(Auth.AuthRequest.getDefaultInstance())); //encoded ch.pipeline().addLast(new LengthFieldPrepender(4)); ch.pipeline().addLast(new ProtobufEncoder()); // 注册handler ch.pipeline().addLast(new AuthServerInitHandler()); } }); b.option(ChannelOption.SO_BACKLOG, 128); b.childOption(ChannelOption.SO_KEEPALIVE, true); //绑定端口 同步等待成功 ChannelFuture f = b.bind(port).sync(); //等待服务端监听端口关闭 f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { logger.log(Level.INFO, "AuthServer start..."); new AuthServer().start(5555); } }
AuthServerInitHandler.java
package com.xinli.netty.protobuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import java.util.logging.Level; import java.util.logging.Logger; public class AuthServerInitHandler extends ChannelInboundHandlerAdapter{ private Logger logger=Logger.getLogger(AuthServerInitHandler.class.getName()); @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { logger.log(Level.INFO, "AuthServerInitHandler channelRead"); Auth.AuthRequest request=(Auth.AuthRequest)msg; System.out.println("request: userId="+request.getUserId()+", password="+request.getPassword()); Auth.AuthResponse response=Auth.AuthResponse.newBuilder() .setResultCode(0) .setResultMessage("success") .build(); ctx.writeAndFlush(response); //ctx.close(); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { logger.log(Level.INFO, "AuthServerInitHandler channelReadComplete"); ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { logger.log(Level.INFO, "AuthServerInitHandler exceptionCaught"); cause.printStackTrace(); ctx.close(); } }
客户端:
Auth.java(Auth.proto编译后的java文件) AuthClient.java AuthClientInitHandler.java
AuthClient.java
package com.xinli.netty.protobuf; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.LengthFieldBasedFrameDecoder; import io.netty.handler.codec.LengthFieldPrepender; import io.netty.handler.codec.protobuf.ProtobufDecoder; import io.netty.handler.codec.protobuf.ProtobufEncoder; public class AuthClient { public void connect(String host,int port) throws Exception{ EventLoopGroup workerGroup=new NioEventLoopGroup(); try{ Bootstrap b=new Bootstrap(); b.group(workerGroup); b.channel(NioSocketChannel.class); b.option(ChannelOption.SO_KEEPALIVE, true); b.handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { //decoded ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4)); ch.pipeline().addLast(new ProtobufDecoder(Auth.AuthResponse.getDefaultInstance())); //encoded ch.pipeline().addLast(new LengthFieldPrepender(4)); ch.pipeline().addLast(new ProtobufEncoder()); // 注册handler ch.pipeline().addLast(new AuthClientInitHandler()); } }); ChannelFuture f=b.connect(host, port).sync(); f.channel().closeFuture().sync(); }finally{ workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { new AuthClient().connect("127.0.0.1", 5555); } }
AuthClientInitHandler.java
package com.xinli.netty.protobuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import java.util.logging.Level; import java.util.logging.Logger; public class AuthClientInitHandler extends ChannelInboundHandlerAdapter{ private Logger logger=Logger.getLogger(AuthClientInitHandler.class.getName()); @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { logger.log(Level.INFO, "AuthClientInitHandler exceptionCaught"); Auth.AuthRequest request=Auth.AuthRequest.newBuilder() .setUserId("010203") .setPassword("abcde") .build(); ctx.writeAndFlush(request); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { logger.log(Level.INFO, "AuthClientInitHandler channelRead"); Auth.AuthResponse response=(Auth.AuthResponse)msg; System.out.println("response: code="+response.getResultCode()+", message="+response.getResultMessage()); //ctx.close(); } }