[英]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.