java - 当简单的 Java Nio 客户端发送消息时 Netty 服务器抛出异常

标签 java c# sockets netty nio

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

我的输出:

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) at 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)

我的服务器程序:

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

我的服务器处理程序:

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 服务器,并消除半个字符串。这对我来说是一个危急的情况。任何帮助将非常感激。

最佳答案

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

似乎有更好的方法,因为您的协议(protocol)在以换行符结尾的行上工作(但这也可能是由于您尝试调试问题引起的),而不是在数据包中添加长度前缀,只需等待使用 DelimiterBasedFrameDecoder 的换行符处理程序,像这样使用它:

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

关于java - 当简单的 Java Nio 客户端发送消息时 Netty 服务器抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44214086/

相关文章:

Java - 从网页源代码中提取明文(从网站获取海量歌词)

java - getX() 调用时出现 NullPointerException(Scene2d + Libgdx)

java - java中的最终变量和同步块(synchronized block)

c# - C# 泛型有性能优势吗?

c# - 将 System.Windows.Media.Imaging.BitmapSource 转换为 System.Drawing.Image

java - InputStream 读取源中不存在的额外字节

java - 文件显示为目录,而不是文件?

windows - I/O完成端口* LAST *称为回调,或: where it's safe to cleanup things

c - 为了将 tcp 程序转换为 udp 需要进行哪些更改

c# - 更改已附加的事件处理程序运行时