Всем привет. Изучаю механизм netty. И вот возник не большой вопрос. Надеюсь вы поможете мне. Итак поехали.
ЧТо я делаю? Создаю обычный сервер, который слушает строку. Если она есть то он выводит ее.
Реализация
Свернуть ↑
Код:
package javaapplication157;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
public class JavaApplication157 {
public static void main(String args[]) throws UnknownHostException {
ChannelFactory factory = new NioServerSocketChannelFactory(
Executors.newFixedThreadPool(1),
Executors.newFixedThreadPool(4) );
ServerBootstrap bootstrap = new ServerBootstrap(factory);
// bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
// @Override
// public ChannelPipeline getPipeline() {
// return Channels.pipeline(new EchoServerHandler());
// }
// });
bootstrap.setPipelineFactory(new NettyServerPipeLineFactory());
bootstrap.setOption("child.tcpNoDelay", true);
bootstrap.setOption("child.keepAlive", true);
bootstrap.bind(new InetSocketAddress(3003));
// Channel chanel = bootstrap.bind(new InetSocketAddress(3003));
System.out.print("NettyServer: Listen to users on "+InetAddress.getLocalHost().toString());
}
}
Свернуть ↑Развернуть ↓
Свернуть ↑
package javaapplication157;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.frame.DelimiterBased FrameDecoder;
import org.jboss.netty.handler.codec.frame.Delimiters;
import org.jboss.netty.handler.codec.string.StringDecoder ;
import org.jboss.netty.handler.codec.string.StringEncoder ;
public class NettyServerPipeLineFactory implements ChannelPipelineFactory {
@Override
public ChannelPipeline getPipeline() throws Exception {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.nulDelimiter()));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("handler", new NettyServerHandler());
return pipeline;
}
}
Свернуть ↑Развернуть ↓
Свернуть ↑
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package javaapplication157;
import java.nio.ByteBuffer;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandl er;
public class NettyServerHandler extends SimpleChannelUpstreamHandler {
private boolean _debug;
public NettyServerHandler() {
_debug = true;
}
@Override
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
super.handleUpstream(ctx, e);
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
log("\nClient connected from "+ctx.getChannel().getRemoteAddress()+" ("+ctx.getChannel().getId()+")");
}
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
log("\nConnection closed from "+ctx.getChannel().getRemoteAddress()+" ("+ctx.getChannel().getId()+")");
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
System.out.println("Bytes");
try {
new CommandProcessorSmall("cmdProcessor", new NetContext(e.getChannel(), (String) e.getMessage()),_debug).start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
log("Error ("+ctx.getChannel().getRemoteAddress()+"): "+e.getCause()+" ("+ctx.getChannel().getId()+")");
e.getChannel().close();
}
private void log(String txt) {
if (_debug) {
System.out.print("NettyServerHandler: "+txt+"\n");
}
}
}
Свернуть ↑Развернуть ↓
Значит рассказываю историю. Пишу к серверу клиентский сендер
Код:
public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException {
// TODO code application logic here
Scanner console = new Scanner(System.in);
Socket sock = new Socket("IP",3003);
PrintWriter writer = new PrintWriter(sock.getOutputStream());
while(true){
System.out.println("Text: ");
String s = console.nextLine();
writer.println(s+"\0");
writer.flush();
}
}
}
Посылаю строки. Ок. Сервер принимает их и выводит на экран. Грубо говоря срабатывает переопределенный метод
messageReceived.
Теперь дальше. Запускаю игру. Конекчусь на сервер в надежде получить ТО что отсылает игра серверу. Не важно поток байтов или что. Просто получить и прочитать так сказать.
Что происходит:
Сервер говорит что есть конект. Следовательно в хэндлере срабатывает channelConnected. Ок.. Казалось бы все хорошо, но сервер не пишет мне то что он получил от игры. Отсюда вывод. Не сработал метод messageReceived.
+ я перестраховался. Просто сделал вывод в консоль сообщения если метод сработал. - Не сработал.
Я немного подумал над тем почему и что так. Перечитав код несколько раз подозрительно оказалось в пайплайне
Код:
public class NettyServerPipeLineFactory implements ChannelPipelineFactory {
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = pipeline();
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.nulDelimiter()));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("handler", new NettyServerHandler());
return pipeline;
}
}
А именно
pipeline.addLast("decoder", new StringDecoder());
Еще точнее StringDecoder()
Что это вабще такое? - Это стандартный строковый декодер. И как я понимаю для пакетов существует отдельный декодер.
Возвращаемся к вопросу почему же сервер ничего не вывел? - Наверно потому что декодер ничего не смог получить из канала поэтому не сработал метод на сообщение... Может быть я не прав.... А вабще это попахивает еще тем, что если не добавить к своей строке \0(конец сообщения) тогда эффект будет тот же самый.
Как я понимаю - мне надо менять декодер. Уважаемые форумчане. Прошу вашей помощи. Если не затруднит то с демонстрацией кода. Большое спасибо.