简体   繁体   English

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

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

I have a very simple Server designed in Java using Netty. 我有一个使用Netty用Java设计的非常简单的服务器。 I have also written a simple client using Java NIO Package. 我还使用Java NIO包编写了一个简单的客户端。 I can connect the Netty Server with the client but when the message is sent to the server I am getting the following exceptions: 我可以将Netty Server与客户端连接,但是当消息发送到服务器时,出现以下异常:

My Output: 我的输出:

New client connected: /127.0.0.1:1125 java.io.IOException: An existing connection was forcibly closed by the remote host at sun.nio.ch.SocketDispatcher.read0(Native Method) at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43) at sun.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.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1100) at 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.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:496) a 已连接新客户端:/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.channel.nio.NioEventLoop.run(NioEventLoop.java:458) at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858) at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:138) at java.lang.Thread.run(Thread.java:745) 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)

My Server Program: 我的服务器程序:

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();
    }
}

My ServerHandler: 我的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();
    }
}

My NIO Java Client: 我的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();
    }

}

Now My required things are: 现在我需要做的事情是:

1) I can't send message from my client to server.Present I am using a Java NIO Client (not Netty). 1)我无法从客户端向服务器发送消息。目前我正在使用Java NIO客户端(不是Netty)。 In future I may send message in bytes from a C# client to the netty server. 将来,我可能会以字节为单位将消息从C#客户端发送到Netty服务器。 Is it possible and if so how to do it? 是否可能,如果可以,怎么办?

2) I am using the LengthFieldBasedFrameDecoder and LengthPrepender to eliminate half strings (the strings that are sent from NETTY client are cut to a size everytime). 2)我正在使用LengthFieldBasedFrameDecoder和LengthPrepender消除半个字符串(从NETTY客户端发送的字符串每次都被切成一个大小)。 I am successfully receiving the message when I use a Netty Client but when I use a different Client designed in Mina or C# I am getting an Exception: length frame exceeded. 使用Netty客户端时,我成功接收到消息,但是当我使用Mina或C#设计的其他客户端时,却出现异常:超出长度框架。 How can I eliminate this? 我该如何消除呢?

In a brief manner I want to connect a client designed in any language which sends bytes to the Netty Server and also eliminate the half strings. 我想以一种简短的方式连接一个以任何语言设计的客户端,该客户端将字节发送到Netty Server,并消除半角字符串。 This is a critical situation for me. 对我来说这是一个危急情况。 Any help would be really appreciable. 任何帮助都是非常可观的。

Since you are using the LengthFieldBasedFrameDecoder in your code, this means that you need to send your packets from simple program in the format this handler accepts, namely, prepended by a 4 byte value in network order that gives the length of the upcoming data. 由于您在代码中使用LengthFieldBasedFrameDecoder ,因此这意味着您需要以简单的程序从处理程序接受的格式发送数据包,即以网络顺序为前缀的4字节值来提供即将到来的数据的长度。

Example for your NIO client 您的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();

There seems to be a better way, since your protocol work on lines ended with a newline (but this may also be caused by your attempts to debug the issue), instead of prefixing the packets with a length, just wait for a newline character using the DelimiterBasedFrameDecoder handler, use it like this: 似乎有更好的方法,因为您的协议在以换行符结尾的行上工作(但这也可能是由于您尝试调试问题所致),而不是给数据包加上长度前缀,只需使用以下命令换行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