2017-05-27 36 views
0

我有一个使用Netty在Java中设计的非常简单的服务器。我还使用Java NIO Package编写了一个简单的客户端。我可以与客户端连接的Netty服务器,但是当消息被发送到服务器,我收到以下情况除外:当一个简单的Java Nio客户端发送消息时,Netty服务器抛出异常

我的输出:

新的客户端连接:/127.0.0.1:1125 java.io.IOException:在sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)sun.nio.ch.SocketDispatcher.read0(Native Method)时,远程主机强制关闭了一个现有连接。 nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)at sun.nio.ch.IOUtil.read(IOUtil.java:192)at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)at io .netty.buffer.PooledUnsafeDirectByteBuf.setBytes(PooledUnsafeDirectByteBuf.java:288)at io。在io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:372)at io.netty.channel.nio.AbstractNioByteChannel $ NioByteUnsafe.read( AbstractNioByteChannel.java:123)at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:644)at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:579)at io.netty.channel .iio.NioEventLoop.processSelectedKeys(NioEventLoop.java:496)at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:458)at io.netty.util.concurrent.SingleThreadEventExecutor $ 5.run(SingleThreadEventExecutor.java: 858)在io.netty.util.concurrent.DefaultThreadFactory $ DefaultRunnableDecorator.run(DefaultThreadFactory.java:138)在java.lang.Thread.run(Thread.java:745)

我的服务器程序:

public class EchoServer{ 

    private final int port; 
    public EchoServer(int port) { 
     this.port = port; 
    } 

    public void start() throws Exception { 
     EventLoopGroup group = new NioEventLoopGroup(); 
     try { 
      ServerBootstrap b = new ServerBootstrap(); 
      b.group(group) 
        .channel(NioServerSocketChannel.class) 
        .localAddress(new InetSocketAddress(port)) 
        .childHandler(new ChannelInitializer<SocketChannel>() { 

      @Override 
      public void initChannel(SocketChannel ch) throws Exception { 
      System.out.println("New client connected: " + ch.localAddress()); 

      ch.pipeline().addLast(newLengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4))    
     .addLast(new LengthFieldPrepender(4)) 
     .addLast(new EchoServerHandler()); 
    } 
     }); 
     ChannelFuture f = b.bind().sync(); 
     f.channel().closeFuture().sync(); 
     } 
     finally { 
      group.shutdownGracefully().sync(); 
     } 
    } 

    public static void main (String [] args) throws Exception { 
     new EchoServer(1125).start(); 
    } 
} 

我ServerHandler:

public class EchoServerHandler extends ChannelInboundHandlerAdapter{ 

    @Override 
    public void channelRead(ChannelHandlerContext ctx, Object msg) { 
     ByteBuf in = (ByteBuf) msg; 
     System.out.println(in.toString(CharsetUtil.UTF_8));   

    } 

     @Override 
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 
     cause.printStackTrace(); 
     ctx.close(); 
    } 
} 

我NIO Java客户端:

public class NIOJavaClient { 

    public static void main(String[] args) throws IOException, InterruptedException { 

     InetSocketAddress addr = new InetSocketAddress("localhost", 1125); 
     SocketChannel client = SocketChannel.open(addr); 

     System.out.println("Connecting to Server on port 1125..."); 

     int i=0; 
     while(i<10){ 

      byte[] message = new String("Hi Server\n").getBytes(); 
      ByteBuffer buffer = ByteBuffer.wrap(message); 
      client.write(buffer); 
      buffer.clear(); 
         i++; 
    } 
     client.close(); 
    } 

} 

现在我需要的东西是:

1)我无法将消息从我的客户端发送到server.Present我正在使用Java NIO Client(不是Netty)。将来,我可能会从C#客户端以字节为单位向netty服务器发送消息。这是可能的,如果是的话如何做到这一点?

2)我使用LengthFieldBasedFrameDecoder和LengthPrepender来消除一半的字符串(从NETTY客户端发送的字符串每次都被剪切为一个大小)。当我使用Netty客户端时,我成功地收到了消息,但是当我使用Mina或C#中设计的不同客户端时,我得到一个异常:超出了长度帧。我怎样才能消除这一点?

在一个简短的方式我想连接一个客户端设计的任何语言发送字节到Netty服务器,也消除了半字符串。这对我来说是一个危急的情况。任何帮助都会非常可观。

回答

2

由于您使用在代码中LengthFieldBasedFrameDecoder,这意味着你需要从简单的程序,在此处理程序接受,即给人的长度格式,通过网络为了一个4字节的值前置送你的包即将到来的数

实例为您的NIO客户

byte[] message = new String("Hi Server\n").getBytes(); 
byte[] fullMessage = new byte[message.length + 4]; 
fullMessage[0] = (byte)(message.length >> 24); 
fullMessage[1] = (byte)(message.length >> 16); 
fullMessage[2] = (byte)(message.length >> 8); 
fullMessage[3] = (byte)message.length; 
System.arraycopy(message, 0, messageFull, 4, message.length); 
ByteBuffer buffer = ByteBuffer.wrap(fullMessage); 
client.write(buffer); 
buffer.clear(); 

似乎是一个更好的办法,因为上线的协议工作以新行结束了(但是这也可以通过你的企图引起调试问题)而不是在数据包前添加长度,只需使用DelimiterBasedFrameDecoder处理程序等待换行符,请使用如下形式:

ch.pipeline.addLast(new DelimiterBasedFrameDecoder(Delimiters.lineDelimiter())) 
// Don't forget to remove your old 2 handlers 
相关问题