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



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

我的输出:

新客户端已连接:/127.0.0.1:1125 java.io.IOException:远程主机在sun.nio.ch.SocketDispatcher.read0(Native Method)在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.read(SocketChannelImpl.java:380)在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 Servern").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 字节的值,该值给出了即将到来的数据的长度。

蔚来汽车客户示例

byte[] message = new String("Hi Servern").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

最新更新