简体   繁体   English

基本Netty回显服务器-字符串编码器错误?

[英]Basic Netty echo server - string encoder error?

This is my first time using Netty and I'm having trouble making a simple echo server! 这是我第一次使用Netty,在制作简单的回显服务器时遇到了麻烦! I looked at docs and it says to use the string encoder and decoder, which I am not using properly apparently. 我看了看文档,并说要使用字符串编码器和解码器,显然我没有正确使用它。 For the framedecoder, I'd like to use the header messages with one byte length, but that doesn't seem to be working either due to the string issue. 对于framedecoder,我想使用一个字节长度的标头消息,但是由于字符串问题,这似乎也不起作用。 I assume my implementation of the PipelineFactory is messed up. 我假设我的PipelineFactory实现被搞砸了。

Bonus Question: 奖励问题:

Because I'm stupid and ambitious, I tried implementing a timeout/heartbeat handler . 因为我既愚蠢又雄心勃勃,所以我尝试实现了超时/心跳处理程序 That didn't work either. 那也不起作用。

Here are the console output and java code: 这是控制台输出和Java代码:

Console: 安慰:

>>telnet localhost 6969
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
>>3
Connection closed by foreign host.

Java Console: Java控制台:

Starting server on 6969
channelConnected
channelDisconnected
java.lang.IllegalArgumentException: unsupported message type: class java.lang.String
    at org.jboss.netty.channel.socket.nio.SocketSendBufferPool.acquire(SocketSendBufferPool.java:51)
    at org.jboss.netty.channel.socket.nio.NioWorker.write0(NioWorker.java:455)
...

Server.java Server.java

public class Server {

    public static void main(String[] args) throws Exception {
        ChannelFactory factory =
                new NioServerSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool());

        ServerBootstrap bootstrap = new ServerBootstrap(factory);

        Timer timer = new HashedWheelTimer();

        bootstrap.setPipelineFactory(new MyPipelineFactory(timer) {
            public ChannelPipeline getPipeline() {
                return Channels.pipeline(new ServerHandler());
            }
        });

        bootstrap.setOption("child.tcpNoDelay", true);
        bootstrap.setOption("child.keepAlive", true);

        bootstrap.bind(new InetSocketAddress(6969));
        System.out.println("Starting server on 6969");
    }
}

ServerHandler.java ServerHandler.java

public class ServerHandler extends SimpleChannelHandler {

    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e){
        Channel ch = e.getChannel();
        System.out.println("channelConnected");
    }

    @Override
    public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e){
        Channel ch = e.getChannel();
        System.out.println("channelDisconnected");
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
        String msg = (String) e.getMessage();
        e.getChannel().write("Did you say '" + msg + "'?\n");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
        e.getCause().printStackTrace();
        Channel ch = e.getChannel();
        ch.close();
    }
}

MyPipelineFactory.java MyPipelineFactory.java

public class MyPipelineFactory implements ChannelPipelineFactory {

    private final Timer timer;
    private static ChannelHandler idleStateHandler;

    public MyPipelineFactory(Timer t) {
        this.timer = t;
        //this.idleStateHandler = new IdleStateHandler(timer, 5, 20, 0); // timer must be shared
    }

    public ChannelPipeline getPipeline() {
        // create default pipeline from static method
        ChannelPipeline pipeline = Channels.pipeline();

        // Decoders
        int maxFrameLength = 1024;
        pipeline.addLast("framer", new DelimiterBasedFrameDecoder(maxFrameLength, Delimiters.lineDelimiter()));
        //pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(maxFrameLength,0,1)); // get header from message
        pipeline.addLast("stringDecoder", new StringDecoder(CharsetUtil.UTF_8));

        // Encoders
        pipeline.addLast("stringEncoder", new StringEncoder(CharsetUtil.UTF_8));

        // Idle state handling- heartbeat
        //pipeline.addLast("idleStateHandler", idleStateHandler);

        return pipeline;
    }

}

Bonus, because I'm stupid and want to get in over my head... 奖励,因为我很愚蠢,想打扰我...

HeartbeatHandler.java HeartbeatHandler.java

public class HeartbeatHandler extends IdleStateAwareChannelHandler {

    @Override
    public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) {
        if (e.getState() == IdleState.READER_IDLE) {
            System.out.println("Reader idle, closing channel");
            e.getChannel().close();
        }
        else if (e.getState() == IdleState.WRITER_IDLE) {
            System.out.println("Writer idle, sending heartbeat");
            e.getChannel().write("heartbeat"); // 
        }
    }
}

It's because you mess up the ChannelPipeline. 这是因为您弄乱了ChannelPipeline。

You use: 你用:

 bootstrap.setPipelineFactory(new MyPipelineFactory(timer) {
        public ChannelPipeline getPipeline() {
            return Channels.pipeline(new ServerHandler());
        }
    });

What you would need todo is modify the MyPipelineFactory class and add your ServerHandler in there. 您需要做的是修改MyPipelineFactory类,然后在其中添加ServerHandler。 Then just set it like: 然后将其设置为:

 bootstrap.setPipelineFactory(new MyPipelineFactory(timer));

Then everything should work. 然后一切都会正常。 Even your timeout stuff ;) 甚至您超时的东西;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM