繁体   English   中英

一个简单的Java Nio客户端发送消息时,Netty Server引发异常

[英]Netty Server throwing Exception when a simple Java Nio Client sends a message

我有一个使用Netty用Java设计的非常简单的服务器。 我还使用Java NIO包编写了一个简单的客户端。 我可以将Netty Server与客户端连接,但是当消息发送到服务器时,出现以下异常:

我的输出:

已连接新客户端:/127.0.0.1:1125 java.io.IOException:远程主机在sun.nio.ch.SocketDispatcher.read0(本机方法)处通过sun.nio.ch.SocketDispatcher.read强制关闭了现有连接。 (SocketDispatcher.java:43),位于sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223),位于sun.nio.ch.IOUtil.read(IOUtil.java:192),位于sun.nio.ch.SocketChannelImpl。在io.netty.channel.socket上从io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1100)在io.netty.buffer.PooledUnsafeDirectByteBuf.setBytes(PooledUnsafeDirectByteBuf.java:288)中读取(SocketChannelImpl.java:380) io.netty.channel.nio.AbstractNioByteChannel $ NioByteUnsafe.read(AbstractNioByteChannel.java:123)上的io.netty.channel.nio.Nio.NioEventLoop.processSelectedKey(NioEventLoop.java)上的.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:372) :644),位于io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:579),位于io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:496)a t io.netty.util.concurrent.SingleThreadEventExecutor $ 5.run(SingleThreadEventExecutor.java:858)的io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:458)io.netty.util.concurrent.DefaultThreadFactory $ java.lang.Thread.run(Thread.java:745)上的DefaultRunnableDecorator.run(DefaultThreadFactory.java:138)

我的服务器程序:

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)我无法从客户端向服务器发送消息。目前我正在使用Java NIO客户端(不是Netty)。 将来,我可能会以字节为单位将消息从C#客户端发送到Netty服务器。 是否可能,如果可以,怎么办?

2)我正在使用LengthFieldBasedFrameDecoder和LengthPrepender消除半个字符串(从NETTY客户端发送的字符串每次都被切成一个大小)。 使用Netty客户端时,我成功接收到消息,但是当我使用Mina或C#设计的其他客户端时,却出现异常:超出长度框架。 我该如何消除呢?

我想以一种简短的方式连接一个以任何语言设计的客户端,该客户端将字节发送到Netty Server,并消除半角字符串。 对我来说这是一个危急情况。 任何帮助都是非常可观的。

由于您在代码中使用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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM