Netty channelRead 从未调用过

Posted

技术标签:

【中文标题】Netty channelRead 从未调用过【英文标题】:Netty channelRead never called 【发布时间】:2014-02-15 13:24:19 【问题描述】:

我玩过 netty 并跟着视频 (https://www.youtube.com/watch?v=tsz-assb1X8) 构建了一个聊天服务器和客户端,服务器正常工作(我用 telnet 测试过,这里可以正常工作)但客户端不接收数据。 ChatClinetHandler.java 中的 channelRead 方法从未被调用,但 channelReadComplete 被调用。

ChatClient.java

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NiosocketChannel;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ChatClient 

    public static void main(String args[]) 
        try 
            new ChatClient(new InetSocketAddress("localhost", 8000)).run();
         catch (Exception ex) 
            Logger.getLogger(ChatClient.class.getName()).log(Level.SEVERE, null, ex);
        
    
    private final InetSocketAddress server;

    public ChatClient(InetSocketAddress server) 
        this.server = server;
    

    public void run() throws Exception 
        EventLoopGroup group = new NioEventLoopGroup();
        try 
            Bootstrap bootstrap = new Bootstrap()
                    .group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ChatClientInitializer());

            Channel channel = bootstrap.connect(server).sync().channel();
            System.out.println("Connected to Server: " + server.toString());
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            while (channel.isActive()) 
                String userMessage = in.readLine();
                channel.writeAndFlush(userMessage + "\r\n");
                if (userMessage.equalsIgnoreCase("bye")) 
                      group.shutdownGracefully();
                      break;
                

            
         finally 
            group.shutdownGracefully();
        
    

ChatClientInitializer.java

import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.DelimiterBasedFrameDecoder; import io.netty.handler.codec.Delimiters; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder;

public class ChatClientInitializer extends ChannelInitializer<SocketChannel> 

    @Override
    protected void initChannel(SocketChannel c) throws Exception 
        ChannelPipeline pipeline = c.pipeline();
        pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
        pipeline.addLast(new StringDecoder());
        pipeline.addLast(new StringEncoder());
        pipeline.addLast(new ChatClientHandler());
     

ChatClinetHandler.java

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;


public class ChatClientHandler extends ChannelInboundHandlerAdapter 
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception 
        System.out.println(msg.toString());
    

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx,
            Throwable cause) 
        cause.printStackTrace();
    


【问题讨论】:

【参考方案1】:

对不起,我忘记在每条消息中发送“\r\n”。

【讨论】:

【参考方案2】:

虽然shim_ claims to have determined that the problem is not sending "\r\n" with each message,但我认为有必要在此澄清一下。

在 ChatClientInitializer.java 中,您会看到一个名为 framer 的处理程序,它是一个 DelimiterBasedFrameDecoder 对象,在该特定示例中带有行分隔符(有关 DelimiterBasedFrameDecoder 的更多信息,请参见 here)。

因此,这意味着客户端期望在该特定频道上以 "\r\n" 结尾的消息。如果收到不以"\r\n"结尾的消息,则不会触发channelRead()方法。

【讨论】:

以上是关于Netty channelRead 从未调用过的主要内容,如果未能解决你的问题,请参考以下文章

Netty中为啥执行channelReadComplete但是不执行channelRead

netty channelhandleradapter 是否去了channelread方法

如何知道 Bytebuf 是从 Netty4 中的哪个通道读取的?

Netty ChannelRead 方法

案例分享Netty线程安全疑问

channelRead对于耗时业务逻辑处理的优化