关于编解码器的介绍,请看我另一篇文章:http://my.oschina.net/xinxingegeya/blog/282878
在这里实现的编解码器很简单,实现int->bytes的编码和bytes->int的解码
具体细节请看代码,注释很全面,运行结果很能说明问题
package codec.encoder; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; public class IntegerToByteEncoder extends MessageToByteEncoder<Integer> { @Override public void encode(ChannelHandlerContext ctx, Integer msg, ByteBuf out) throws Exception { System.err.println("IntegerToByteEncoder encode msg is " + msg); out.writeInt(msg); } }
package codec.decoder; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import java.util.List; /** * 把字节转换为int * 继承抽象类ByteToMessageDecoder实现解码器 */ public class ByteToIntegerDecoder extends ByteToMessageDecoder { @Override public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { if (in.readableBytes() >= 4) { // Check if there are at least 4 bytes readable int n = in.readInt(); System.err.println("ByteToIntegerDecoder decode msg is " + n); out.add(n); //Read integer from inbound ByteBuf, add to the List of decodec messages } } }
package codec; import codec.decoder.ByteToIntegerDecoder; import codec.encoder.IntegerToByteEncoder; 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; /** * 主要思路: * 实现了一个编码器IntegerToByteEncoder和一个解码器ByteToIntegerDecoder * 客户端直接发送一个数字 * 服务器端接收后向客户端发送一个数字 * 在这过程中可以看到解码器和编码器所起的作用 */ public class HelloServer { public void start(int port) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 128) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { // 注册handler ch.pipeline().addLast( new IntegerToByteEncoder(), new ByteToIntegerDecoder(), new HelloServerInHandler()); } }); ChannelFuture f = b.bind(port).sync(); f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { HelloServer server = new HelloServer(); server.start(12345); } }
package codec; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; // 该handler是InboundHandler类型 public class HelloServerInHandler extends ChannelInboundHandlerAdapter { @Override public boolean isSharable() { System.out.println("==============handler-sharable=============="); return super.isSharable(); } @Override public void channelRegistered(ChannelHandlerContext ctx) throws Exception { System.out.println("==============channel-register=============="); } @Override public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { System.out.println("==============channel-unregister=============="); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("==============channel-active=============="); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("==============channel-inactive=============="); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("==============channel-read=============="); System.out.println("the msg type is " + msg.getClass().getName()); Integer integer = (Integer) msg; System.out.println("服务器端接收到的客户端的数字是" + integer); System.out.println("服务器向客户端写入整型数字2000"); ctx.writeAndFlush(2000); ctx.close(); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { System.out.println("==============channel-read-complete=============="); ctx.flush(); } }
package codec; import codec.decoder.ByteToIntegerDecoder; import codec.encoder.IntegerToByteEncoder; 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; public class HelloClient { 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.AUTO_READ, true); b.handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast( new IntegerToByteEncoder(), new ByteToIntegerDecoder(), new HelloClientIntHandler()); } }); ChannelFuture f = b.connect(host, port).sync(); f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { HelloClient client = new HelloClient(); client.connect("192.168.0.102", 12345); } }
package codec; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; //InboundHandler类型 public class HelloClientIntHandler extends ChannelInboundHandlerAdapter { @Override public void channelRegistered(ChannelHandlerContext ctx) throws Exception { System.out.println("==============channel--register=============="); } @Override public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { System.out.println("==============channel--unregistered=============="); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("==============channel--inactive=============="); } // 连接成功后,向server发送消息 @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("==============channel--active=============="); System.out.println("向服务器端写入1991数字"); ctx.write(1991); ctx.flush(); } // 接收server端的消息,并打印出来 @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("==============channel--read=============="); System.out.println("the msg type is " + msg.getClass().getName()); Integer result = (Integer) msg; System.out.println("接收到服务器数据整形是" + result); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } }
服务器端
==============handler-sharable==============
==============channel-register==============
==============channel-active==============
==============channel-read==============
the msg type is java.lang.Integer
服务器端接收到的客户端的数字是1991
服务器向客户端写入整型数字2000
ByteToIntegerDecoder decode msg is 1991
IntegerToByteEncoder encode msg is 2000
==============channel-read-complete==============
==============channel-inactive==============
==============channel-unregister==============
客户端
==============channel--register==============
==============channel--active==============
向服务器端写入1991数字
IntegerToByteEncoder encode msg is 1991
ByteToIntegerDecoder decode msg is 2000
==============channel--read==============
the msg type is java.lang.Integer
接收到服务器数据整形是2000
==============channel--inactive==============
==============channel--unregistered==============
Process finished with exit code 0