Basic Netty echo server string encoder-Fehler?
Dies ist mein erstes mal mit Netty und ich habe Mühe, einen einfachen echo-server! Ich schaute auf Google docs, und es sagt die string-encoder und-decoder, die ich bin nicht mit richtig offenbar. Für die framedecoder, würde ich gerne den header von Nachrichten mit einem byte Länge, aber das scheint nicht zu arbeiten, entweder durch das string-Problem. Ich nehme an, dass meine Umsetzung der PipelineFactory versaut ist.
Bonus-Frage:
Weil ich dumm bin und ehrgeizig, ich habe versucht, die Implementierung eines timeout/Herzschlag-hf. Das hat nicht funktioniert entweder.
Hier die Ausgabe der Konsole und java-code:
Konsole:
>>telnet localhost 6969
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
>>3
Connection closed by foreign host.
Java-Konsole:
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;
}
}
Bonus, weil ich bin dumm und möchte über meinen Kopf...
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"); //
}
}
}
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es ist, weil Sie mess up das ChannelPipeline.
Verwendung:
Was Sie brauchen todo ist ändern Sie die MyPipelineFactory Klasse und fügen Sie Ihre ServerHandler dort. Dann einfach alles einstellen wie:
Dann sollte alles funktionieren. Auch Ihr timeout Zeug 😉
ChannelPipeline pipeline = Channels.pipeline(new ServerHandler());
stattChannelPipeline pipeline = Channels.pipeline();
die gab mir die gleiche string-Fehler. Ich habe auch versucht, den ServerHandler eine Klasse, variable und übergeben, dass auf den Kanal.pipeline. Ich bin eindeutig etwas fehlt.