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

时间:2012-02-14 04:01:38

标签: java sockets jboss network-programming netty

这是我第一次使用Netty而我在创建一个简单的echo服务器时遇到了麻烦!我查看了文档,它说要使用字符串编码器和解码器,我显然没有使用它。对于framedecoder,我想使用一个字节长度的头消息,但由于字符串问题,这似乎不起作用。我假设我对PipelineFactory的实现搞砸了。

奖金问题:

因为我愚蠢而且雄心勃勃,我尝试实施timeout/heartbeat handler。这也不起作用。

以下是控制台输出和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"); // 
        }
    }
}

1 个答案:

答案 0 :(得分:1)

这是因为你弄乱了ChannelPipeline。

您使用:

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

您需要的是修改MyPipelineFactory类并在其中添加ServerHandler。然后将它设置为:

 bootstrap.setPipelineFactory(new MyPipelineFactory(timer));

然后一切都应该有效。甚至你的超时东西;)