Netty客户端实现

Netty客户端实现教程

和服务端实现类似,Netty 客户端也需要实现相应的编解码逻辑,只不过具体的业务处理逻辑,客户端不需要关心,因为已经在服务端进行处理了。

Netty客户端具体实现

对应的编解码请求流程如下图:

07 客户端编解码.png

代码

客户端编解码的代码结构图如下:

08 客户端编解码代码结构.png

业务数据编码OrderProtocolEncoder

package io.netty.client.codec; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.common.RequestMessage; import io.netty.handler.codec.MessageToMessageEncoder; import java.util.List; /** * @author 嗨客网 * @description 二次解码器 */ public class OrderProtocolEncoder extends MessageToMessageEncoder<RequestMessage> { @Override protected void encode(ChannelHandlerContext ctx, RequestMessage requestMessage, List<Object> out) throws Exception { ByteBuf buffer = ctx.alloc().buffer(); requestMessage.encode(buffer); out.add(buffer); } }

拆包粘包编码OrderFrameEncoder

package io.netty.client.codec; import io.netty.handler.codec.LengthFieldPrepender; /** * @author 嗨客网 * @description */ public class OrderFrameEncoder extends LengthFieldPrepender { /** * 得到没有粘包和半包的 bytebuf */ public OrderFrameEncoder() { super(2); } }

拆包粘包解码OrderFrameDecoder

package io.netty.client.codec; import io.netty.handler.codec.LengthFieldBasedFrameDecoder; /** * @author 嗨客网 * @description */ public class OrderFrameDecoder extends LengthFieldBasedFrameDecoder { /** * 得到没有粘包和半包的 bytebuf */ public OrderFrameDecoder() { super(Integer.MAX_VALUE, 0, 2, 0, 2); } }

业务数据解码OrderProtocolDecoder

package io.netty.client.codec; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.common.ResponseMessage; import io.netty.handler.codec.MessageToMessageDecoder; import java.util.List; /** * @author 嗨客网 * @description 二次解码器 */ public class OrderProtocolDecoder extends MessageToMessageDecoder<ByteBuf> { /** * 把 Bytebuf 对象转换成 requestmessage 对象 * * @param ctx * @param msg * @param out * @throws Exception */ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception { ResponseMessage responseMessage = new ResponseMessage(); responseMessage.decode(msg); out.add(responseMessage); } }

组织客户端编解码

Client

package io.netty.client; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.client.codec.OrderFrameDecoder; import io.netty.client.codec.OrderFrameEncoder; import io.netty.client.codec.OrderProtocolDecoder; import io.netty.client.codec.OrderProtocolEncoder; import io.netty.common.RequestMessage; import io.netty.common.order.OrderOperation; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import io.netty.util.IdUtil; /** * @author 嗨客网 * @description 组织编解码 */ public class Client { public static void main(String[] args) throws Exception { Bootstrap bootstrap = new Bootstrap(); bootstrap.channel(NioSocketChannel.class); bootstrap.group(new NioEventLoopGroup()); //处理具体逻辑是 childHandler 来处理的 bootstrap.handler(new ChannelInitializer<NioSocketChannel>() { @Override protected void initChannel(NioSocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new OrderFrameDecoder()); pipeline.addLast(new OrderFrameEncoder()); pipeline.addLast(new OrderProtocolEncoder()); pipeline.addLast(new OrderProtocolDecoder()); pipeline.addLast(new LoggingHandler(LogLevel.INFO)); } }); ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 8090); channelFuture.sync(); RequestMessage requestMessage = new RequestMessage(IdUtil.nextId(), new OrderOperation(1001, "小鸡炖蘑菇")); channelFuture.channel().writeAndFlush(requestMessage); channelFuture.channel().closeFuture().get(); } }

客户端实现总结

本章节,我们定义了客户端编解码器,并且定义了一个 client 类将编解码器进行了组织连接。这样就可以将客户端和服务端进行通信了。