簡體   English   中英

基本Netty回顯服務器-字符串編碼器錯誤?

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

這是我第一次使用Netty,在制作簡單的回顯服務器時遇到了麻煩! 我看了看文檔,並說要使用字符串編碼器和解碼器,顯然我沒有正確使用它。 對於framedecoder,我想使用一個字節長度的標頭消息,但是由於字符串問題,這似乎也不起作用。 我假設我的PipelineFactory實現被搞砸了。

獎勵問題:

因為我既愚蠢又雄心勃勃,所以我嘗試實現了超時/心跳處理程序 那也不起作用。

這是控制台輸出和Java代碼:

安慰:

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

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

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

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

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;
    }

}

獎勵,因為我很愚蠢,想打擾我...

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"); // 
        }
    }
}

這是因為您弄亂了ChannelPipeline。

你用:

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

您需要做的是修改MyPipelineFactory類,然后在其中添加ServerHandler。 然后將其設置為:

 bootstrap.setPipelineFactory(new MyPipelineFactory(timer));

然后一切都會正常。 甚至您超時的東西;)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM