Question

I'm trying to modify the securechat example of netty to send bytes (byte array) instead of a string.But I'm unable to send any bytes to the server. what am I doing wrong? It works perfectly if an ObjectDecoder/Encoder is used, but I need raw bytes to be send through the wire.

If instead if a byte[], a ByteBuffer would also suffice, as long as The traffic consists of only those bytes within the buffer.

Can anyone please help?

Client.java

public class Client {

private final String host;
private final int port;

public Client(String host, int port) {
    this.host = host;
    this.port = port;
}

public void run() throws Exception {
    EventLoopGroup group = new NioEventLoopGroup();
    try {
        Bootstrap b = new Bootstrap();
        b.group(group)
         .channel(NioSocketChannel.class)
         .handler(new ClientInitializer());
        Channel ch = b.connect(host, port).sync().channel();
        ChannelFuture lastWriteFuture = null;
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        for (;;) {
            String line = in.readLine();
            if (line == null) {
                break;
            }

            lastWriteFuture = ch.write(new byte[]{1,2,3,4,5,6,7,8});

        }
        if (lastWriteFuture != null) {
            lastWriteFuture.sync();
        }
    } finally {
        group.shutdownGracefully();
    }
}

public static void main(String[] args) throws Exception {
    new Client("localhost",6666).run();
}
}

ClientHandler

public class ClientHandler extends SimpleChannelInboundHandler<Byte[]> {

private static final Logger logger = Logger.getLogger(
        ClientHandler.class.getName());

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    logger.log(
            Level.WARNING,
            "Unexpected exception from downstream.", cause);
    ctx.close();
}

@Override
protected void channelRead0(ChannelHandlerContext chc, Byte[] i) throws Exception {
   System.out.println(i[3]);
}
}

ClientInitializer

public class ClientInitializer extends ChannelInitializer<SocketChannel> {

@Override
public void initChannel(SocketChannel ch) throws Exception {
    ChannelPipeline pipeline = ch.pipeline();

  pipeline.addLast("frameDecoder",
            new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4));
    pipeline.addLast("bytesDecoder",
            new ByteArrayDecoder());

    pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
    pipeline.addLast("bytesEncoder", new ByteArrayEncoder());
    pipeline.addLast("handler", new ClientHandler());
}
}

Server

public class Server {
private final int port;
public Server(int port) {
    this.port = port;
}
public void run() throws InterruptedException {
    EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    try {
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup)
         .channel(NioServerSocketChannel.class)
         .childHandler(new ServerInitializer());

        b.bind(port).sync().channel().closeFuture().sync();
    } finally {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}
public static void main(String[] args) throws Exception {
    int port;
    if (args.length > 0) {
        port = Integer.parseInt(args[0]);
    } else {
        port = 6666;
    }
    new Server(port).run();
}
}

ServerHandler

public class ServerHandler extends SimpleChannelInboundHandler<Byte[]> {
private static final Logger logger = Logger.getLogger(
        ServerHandler.class.getName());

static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

@Override
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
            channels.add(ctx.channel());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    logger.log(
            Level.WARNING,
            "Unexpected exception from downstream.", cause);
    ctx.close();
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Byte[] i) throws Exception {
    for (Channel c: channels) {
        if (c != ctx.channel()) {
            c.writeAndFlush(i);
        } 
    }

}
}

ServerInitializer

public class ServerInitializer extends ChannelInitializer<SocketChannel> {

@Override
public void initChannel(SocketChannel ch) throws Exception {
    ChannelPipeline pipeline = ch.pipeline();
    pipeline.addLast("frameDecoder",
            new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4));
    pipeline.addLast("bytesDecoder",
            new ByteArrayDecoder());
    pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
    pipeline.addLast("bytesEncoder", new ByteArrayEncoder());
    pipeline.addLast("handler", new ServerHandler());
 }
}
Was it helpful?

Solution

You forgot to call channel.flush() in your client after channel.write(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }). Because it was never flushed, the server will never receive it. Alternatively, you can use writeAndFlush() which is a shortcut of write(...) and flush().

OTHER TIPS

Just found this example need change to byte[], otherwise it will not be called.

public class ServerHandler extends SimpleChannelInboundHandler < byte[]> {
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top