Reputation: 383
I have a very simple Server designed in Java using Netty. I have also written a simple client using Java NIO Package. I can connect the Netty Server with the client but when the message is sent to the server I am getting the following exceptions:
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) 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)
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:
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:
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). In future I may send message in bytes from a C# client to the netty server. 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). 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. 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. This is a critical situation for me. Any help would be really appreciable.
Upvotes: 0
Views: 898
Reputation: 18834
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.
Example for your NIO client
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:
ch.pipeline.addLast(new DelimiterBasedFrameDecoder(Delimiters.lineDelimiter()))
// Don't forget to remove your old 2 handlers
Upvotes: 2