这是我第一次使用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"); //
}
}
}
答案 0 :(得分:1)
这是因为你弄乱了ChannelPipeline。
您使用:
bootstrap.setPipelineFactory(new MyPipelineFactory(timer) {
public ChannelPipeline getPipeline() {
return Channels.pipeline(new ServerHandler());
}
});
您需要的是修改MyPipelineFactory类并在其中添加ServerHandler。然后将它设置为:
bootstrap.setPipelineFactory(new MyPipelineFactory(timer));
然后一切都应该有效。甚至你的超时东西;)