Netty框架中文编码(二)
2023-04-12
netty实战
- 1. 背景
- 2. 思路
- 3. 实现
- 4. 日志分析
- 5. 总结
1. 背景
我在上一篇文章中提到,假如针对老系统升级,面向的客户端是不同的主体,并且因为各种原因出现了编码不一致的问题(实际情况下很难出现的场景),那么我们该如何处理?之前我想到一种办法是使用Nginx代理stream,但是经过验证不可行。后边我还有一种想法是通过程序来实现,根据对端的IP来指定不同的编码方式,采用配置化的方式实现。此种方式有待于进一步学习动态handler来进行验证。今天我就简单记录下实战情况。
2. 思路
- 初始化initChannel时,先获取客户端IP
- 根据客户端IP,动态实现不同编码
3. 实现
- handler
public class CodeHandler extends ChannelInboundHandlerAdapter {
public static final Logger log = LoggerFactory.getLogger(CodeHandler.class);
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
log.info("服务端接收消息是:{}", msg);
ctx.write(msg);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
log.info("exceptionCaught: " + cause.getLocalizedMessage());
}
}
- server
public class CodeServer {
public static final Logger log = LoggerFactory.getLogger(CodeServer.class);
private final String ip = "192.168.0.118";
private final String port = "8001";
public void init(){
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap bs = new ServerBootstrap();
bs.group(bossGroup, workerGroup);
bs.channel(NioServerSocketChannel.class);
bs.childHandler(new ChannelInitializer(){
@Override
protected void initChannel(Channel ch) throws Exception {
final ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new LoggingHandler(LogLevel.INFO));
String remoteAddress = ch.remoteAddress().toString();
log.info("远程地址:" + ch.remoteAddress().toString());
if (remoteAddress.contains("192.168.0.118")) {
log.info("UTF-8编码");
pipeline.addLast(new StringDecoder(Charset.forName("UTF-8")));
pipeline.addLast(new StringEncoder(Charset.forName("UTF-8")));
} else {
log.info("GBK编码");
pipeline.addLast(new StringDecoder(Charset.forName("GBK")));
pipeline.addLast(new StringEncoder(Charset.forName("GBK")));
}
log.info("添加业务handler");
pipeline.addLast(new CodeHandler());
}
});
try {
ChannelFuture channelFuture = bs.bind(ip, Integer.parseInt(port)).sync();
log.info("Netty Server 启动成功! Ip: " + channelFuture.channel().localAddress().toString() + " ! ");
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
- 客户端模拟单元测试
public class CodeClient {
public static final Logger log = LoggerFactory.getLogger(CodeClient.class);
public void connect(int port, String host) throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer() {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
final ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new LoggingHandler(LogLevel.INFO));
// 不同内网机器,实验时灵活切换
// 比如192.168.0.118为UTF-8,192.168.0.105为GBK
//pipeline.addLast(new StringEncoder(Charset.forName("UTF-8")));
pipeline.addLast(new StringEncoder(Charset.forName("GBK")));
}
});
ChannelFuture future = bootstrap.connect("192.168.0.118", 8001).sync();
future.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
future.channel().writeAndFlush("你好");
}
});
future.syncUninterruptibly();
future.channel().closeFuture().sync();
}
public static void main(String[] args) throws InterruptedException {
new CodeClient().connect(8001, "192.168.0.118");
}
}
4. 日志分析
- 192.168.0.118日志记录
可以看到后台接收6B,为UTF-8编码。
10:43:08.021 [nioEventLoopGroup-3-4] INFO com.ll.demo2.CodeServer - 远程地址:/192.168.0.118:5756
10:43:08.021 [nioEventLoopGroup-3-4] INFO com.ll.demo2.CodeServer - UTF-8编码
10:43:08.021 [nioEventLoopGroup-3-4] INFO com.ll.demo2.CodeServer - 添加业务handler
10:43:08.022 [nioEventLoopGroup-3-4] INFO io.netty.handler.logging.LoggingHandler - [id: 0xbe4fd2ce, L:/192.168.0.118:8001 - R:/192.168.0.118:5756] REGISTERED
10:43:08.022 [nioEventLoopGroup-3-4] INFO io.netty.handler.logging.LoggingHandler - [id: 0xbe4fd2ce, L:/192.168.0.118:8001 - R:/192.168.0.118:5756] ACTIVE
10:43:08.053 [nioEventLoopGroup-3-4] INFO io.netty.handler.logging.LoggingHandler - [id: 0xbe4fd2ce, L:/192.168.0.118:8001 - R:/192.168.0.118:5756] READ: 6B
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| e4 bd a0 e5 a5 bd |...... |
+--------+-------------------------------------------------+----------------+
10:43:08.053 [nioEventLoopGroup-3-4] INFO com.ll.demo2.CodeHandler - 服务端接收消息是:你好
10:43:08.054 [nioEventLoopGroup-3-4] INFO io.netty.handler.logging.LoggingHandler - [id: 0xbe4fd2ce, L:/192.168.0.118:8001 - R:/192.168.0.118:5756] WRITE: 6B
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| e4 bd a0 e5 a5 bd |...... |
+--------+-------------------------------------------------+----------------+
10:43:08.054 [nioEventLoopGroup-3-4] INFO io.netty.handler.logging.LoggingHandler - [id: 0xbe4fd2ce, L:/192.168.0.118:8001 - R:/192.168.0.118:5756] READ COMPLETE
10:43:08.054 [nioEventLoopGroup-3-4] INFO io.netty.handler.logging.LoggingHandler - [id: 0xbe4fd2ce, L:/192.168.0.118:8001 - R:/192.168.0.118:5756] FLUSH
- 192.168.0.105日志记录
可以看到后台接收4B,为GBK编码。
10:41:54.537 [nioEventLoopGroup-3-3] INFO com.ll.demo2.CodeServer - 远程地址:/192.168.0.105:49630
10:41:54.537 [nioEventLoopGroup-3-3] INFO com.ll.demo2.CodeServer - GBK编码
10:41:54.537 [nioEventLoopGroup-3-3] INFO com.ll.demo2.CodeServer - 添加业务handler
10:41:54.538 [nioEventLoopGroup-3-3] INFO io.netty.handler.logging.LoggingHandler - [id: 0x9da24e21, L:/192.168.0.118:8001 - R:/192.168.0.105:49630] REGISTERED
10:41:54.538 [nioEventLoopGroup-3-3] INFO io.netty.handler.logging.LoggingHandler - [id: 0x9da24e21, L:/192.168.0.118:8001 - R:/192.168.0.105:49630] ACTIVE
10:41:54.560 [nioEventLoopGroup-3-3] INFO io.netty.handler.logging.LoggingHandler - [id: 0x9da24e21, L:/192.168.0.118:8001 - R:/192.168.0.105:49630] READ: 4B
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| c4 e3 ba c3 |.... |
+--------+-------------------------------------------------+----------------+
10:41:54.560 [nioEventLoopGroup-3-3] INFO com.ll.demo2.CodeHandler - 服务端接收消息是:你好
10:41:54.561 [nioEventLoopGroup-3-3] INFO io.netty.handler.logging.LoggingHandler - [id: 0x9da24e21, L:/192.168.0.118:8001 - R:/192.168.0.105:49630] WRITE: 4B
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| c4 e3 ba c3 |.... |
+--------+-------------------------------------------------+----------------+
10:41:54.561 [nioEventLoopGroup-3-3] INFO io.netty.handler.logging.LoggingHandler - [id: 0x9da24e21, L:/192.168.0.118:8001 - R:/192.168.0.105:49630] READ COMPLETE
10:41:54.561 [nioEventLoopGroup-3-3] INFO io.netty.handler.logging.LoggingHandler - [id: 0x9da24e21, L:/192.168.0.118:8001 - R:/192.168.0.105:49630] FLUSH
5. 总结
日志对比之后,发现可以根据不同IP区分开,并且中文编解码都正常。这样就解决了面对不同客户端主体的时候,可以进行编码的灵活配置了。
本文仅代表作者观点,版权归原创者所有,如需转载请在文中注明来源及作者名字。
免责声明:本文系转载编辑文章,仅作分享之用。如分享内容、图片侵犯到您的版权或非授权发布,请及时与我们联系进行审核处理或删除,您可以发送材料至邮箱:service@tojoy.com




