关于Netty中连接到了客户端,只调用了channelReadComplete,没走channelRead。
今天自己练习的时候,根据网上的代码进行测试。
public class TcpServerHandler extends SimpleChannelInboundHandler<ByteBuf> {
@Autowired
private RocketMQTemplate rocketMQTemplate;
@Autowired
@Qualifier("businessGroup")
private EventExecutorGroup businessGroup;
/**
* 使用
*
* @param ctx
* @param byteBuf
* @throws Exception
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf byteBuf) {
String content = byteBuf.toString(StandardCharsets.UTF_8);
log.info("TCP服务端接收到消息:{}", content);
ByteBuf buf = Unpooled.copiedBuffer("TCP已经接收到消息:".getBytes(StandardCharsets.UTF_8));
businessGroup.execute(() -> {
try {
rocketMQTemplate.convertAndSend("zp-consumer-rockrt-netty-test", content);
send2client(ctx, buf.array());
} catch (Throwable e) {
log.error("TCP数据接收处理出错", e);
ByteBuf err = Unpooled.copiedBuffer("系统错误:".getBytes(StandardCharsets.UTF_8));
send2client(ctx, err.array());
}
});
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
log.error("TCP数据接收处理出错:", cause);
}
/**
* 返回消息给客户端
*
* @param ctx
* @param msg
*/
void send2client(ChannelHandlerContext ctx, byte[] msg) {
ByteBuf buf = Unpooled.buffer(msg.length + 1);
buf.writeBytes(msg);
buf.writeByte(MsgUtil.DELIMITER);
ctx.channel().writeAndFlush(buf).addListener(future -> {
if (!future.isSuccess()) {
log.error("TCP发送给客户端消息失败");
}
});
}
上图为ServerHandler代码。
/**
* netty服务(TCP)
*/
@Slf4j
@Component
public class NettyTcpServer implements ApplicationListener<ApplicationStartedEvent> {
@Value("${netty.tcp.port}")
private int port;
@Value("${netty.tcp.read-timeout}")
private int readTimeOut;
@Autowired
@Qualifier("bossGroup")
private NioEventLoopGroup bossGroup;
@Autowired
@Qualifier("workerGroup")
private NioEventLoopGroup workerGroup;
@Autowired
@Qualifier("businessGroup")
private EventExecutorGroup businessGroup;
@Autowired
private TcpServerHandler tcpServerHandler;
@Autowired
private MyServerHandler myServerHandler;
private ChannelFuture channelFuture;
private org.slf4j.Logger logger = LoggerFactory.getLogger(NettyTcpServer.class);
/**
* 启动Server
*
*/
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() { //
@Override
public void initChannel(SocketChannel channel) throws Exception {
// 日志打印
channel.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
// 基于换行符号
// channel.pipeline().addLast(new LineBasedFrameDecoder(1024));
// 解码转String,注意调整自己的编码格式GBK,UTF-8
channel.pipeline().addLast(new StringDecoder(Charset.forName("GBK")));
// 解码转String,注意调整自己的编码格式GBK,UTF-8
channel.pipeline().addLast(new StringEncoder(Charset.forName("GBK")));
// channel.pipeline().addLast(new IdleStateHandler(readTimeOut, 0, 0, TimeUnit.MINUTES));
// 1024表示单条消息的最大长度,解码器在查找分隔符的时候,达到该长度还没找到的话会抛异常
// channel.pipeline().addLast(
// new DelimiterBasedFrameDecoder(1024, Unpooled.copiedBuffer(new byte[] { MsgUtil.DELIMITER }),
// Unpooled.copiedBuffer(new byte[] { MsgUtil.DELIMITER, MsgUtil.DELIMITER })));
channel.pipeline().addLast(myServerHandler);
}
})
.option(ChannelOption.SO_BACKLOG, 128) //服务端可连接队列数,对应TCP/IP协议listen函数中backlog参数
.childOption(ChannelOption.TCP_NODELAY, true)//立即写出
.childOption(ChannelOption.SO_KEEPALIVE, true);//长连接
channelFuture = serverBootstrap.bind(port).sync();
if (channelFuture.isSuccess()) {
log.info("TCP服务启动完毕,port={}", port);
}
}catch(Exception e) {
log.info("TCP服务启动失败", e);
}finally {
if (null != channelFuture && channelFuture.isSuccess()){
logger.info("netty server start done 、netty服务已经开始");
}else {
logger.error("netty server start error、netty服务开始错误");
}
}
}
/**
* 销毁资源
*/
@PreDestroy
public void destroy() {
bossGroup.shutdownGracefully().syncUninterruptibly();
workerGroup.shutdownGracefully().syncUninterruptibly();
log.info("TCP服务关闭成功");
}
}
上图因为添加了下面这段代码
// 基于换行符号
channel.pipeline().addLast(new LineBasedFrameDecoder(1024));
导致只调用了channelReadComplete,没走channelRead。