Java Netty:在服务器启动后启动客户端,为什么需要另一个线程?

Java Netty:在服务器启动后启动客户端,为什么需要另一个线程?,java,multithreading,tcp,netty,Java,Multithreading,Tcp,Netty,我想在一个应用程序中启动TCP echo服务器和客户端,一个客户端接一个服务器 我所做的是: 在server.bind().sync()返回的ChannelFutureListener中启动客户端,如下所示: public void runClientAndServer() { server.run().addListener((ChannelFutureListener) future -> { // client.run();

我想在一个应用程序中启动TCP echo服务器和客户端,一个客户端接一个服务器

我所做的是: 在
server.bind().sync()
返回的
ChannelFutureListener
中启动客户端,如下所示:

public void runClientAndServer() {
    server.run().addListener((ChannelFutureListener) future -> {
        // client.run();                        //(1) this doesn't work!
        new Thread(()->client.run()).start();   //(2) this works!
    });
}
public ChannelFuture run() {
    ServerBootstrap b = new ServerBootstrap();
    //doing channel config stuff
    return b.bind(6666).sync();
}
public void run() {
    Bootstrap b = new Bootstrap();
    //do some config stuff
    f = b.connect(host, port).sync(); //wait till connected to server
}
server.run()
是这样的:

public void runClientAndServer() {
    server.run().addListener((ChannelFutureListener) future -> {
        // client.run();                        //(1) this doesn't work!
        new Thread(()->client.run()).start();   //(2) this works!
    });
}
public ChannelFuture run() {
    ServerBootstrap b = new ServerBootstrap();
    //doing channel config stuff
    return b.bind(6666).sync();
}
public void run() {
    Bootstrap b = new Bootstrap();
    //do some config stuff
    f = b.connect(host, port).sync(); //wait till connected to server
}
client.run()
是这样的:

public void runClientAndServer() {
    server.run().addListener((ChannelFutureListener) future -> {
        // client.run();                        //(1) this doesn't work!
        new Thread(()->client.run()).start();   //(2) this works!
    });
}
public ChannelFuture run() {
    ServerBootstrap b = new ServerBootstrap();
    //doing channel config stuff
    return b.bind(6666).sync();
}
public void run() {
    Bootstrap b = new Bootstrap();
    //do some config stuff
    f = b.connect(host, port).sync(); //wait till connected to server
}
发生的情况是: 在声明(2)中,它的效果很好;在语句(1)中,客户端发送了可以在Wireshark中观察到的消息,服务器回复TCP
ACK
段,但没有调用服务器端
ChannelInboundHandlerAdapter
中的
channelRead()
方法,也无法观察到将消息写入套接字的任何尝试,如以下捕获:


我猜Netty线程一定有问题,但我就是搞不清楚,我已经准备了一个基于最新Netty版本(4.1.16.Final)和您发布的代码的示例。这在没有额外线程的情况下运行良好,可能是您在初始化服务器或客户端时出错了

private static final NioEventLoopGroup EVENT_LOOP_GROUP = new NioEventLoopGroup();

private static ChannelFuture runServer() throws Exception {
    return new ServerBootstrap()
            .group(EVENT_LOOP_GROUP)
            .channel(NioServerSocketChannel.class)
            .childHandler(new ChannelInitializer<Channel>() {

                @Override
                protected void initChannel(Channel channel) throws Exception {
                    System.out.println("S - Channel connected: " + channel);

                    channel.pipeline().addLast(new SimpleChannelInboundHandler<ByteBuf>() {

                        @Override
                        protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
                            System.out.println("S - read: " + msg.toString(StandardCharsets.UTF_8));
                        }
                    });
                }
            })
            .bind(6666).sync();
}

private static void runClient() throws Exception {
    new Bootstrap()
        .group(EVENT_LOOP_GROUP)
        .channel(NioSocketChannel.class)
        .handler(new ChannelInitializer<Channel>() {

            @Override
            protected void initChannel(Channel channel) throws Exception {
                System.out.println("C - Initilized client");

                channel.pipeline().addLast(new SimpleChannelInboundHandler<ByteBuf>() {

                    @Override
                    public void channelActive(ChannelHandlerContext ctx) throws Exception {
                        super.channelActive(ctx);
                        System.out.println("C - write: Hey this is a test message enjoy!");
                        ctx.writeAndFlush(Unpooled.copiedBuffer("Hey this is a test message enjoy!".getBytes(StandardCharsets.UTF_8)));
                    }

                    @Override
                    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { }
                });
            }
        })
        .connect("localhost", 6666).sync();
}

public static void main(String[] args) throws Exception {
    runServer().addListener(future -> {
        runClient();
    });
}

我还用一个单线程eventloopgroup尝试了这个例子,它也工作得很好,但是抛出了一个不影响程序功能的错误。如果此代码工作正常,您可能应该检查您的代码,并尝试在此示例中确定代码的方向(请不要像我在本示例中所做的那样为您的实际项目创建内联ChannelHandler)。

我根据最新的netty版本(4.1.16.Final)和您发布的代码准备了一个示例。这在没有额外线程的情况下运行良好,可能是您在初始化服务器或客户端时出错了

private static final NioEventLoopGroup EVENT_LOOP_GROUP = new NioEventLoopGroup();

private static ChannelFuture runServer() throws Exception {
    return new ServerBootstrap()
            .group(EVENT_LOOP_GROUP)
            .channel(NioServerSocketChannel.class)
            .childHandler(new ChannelInitializer<Channel>() {

                @Override
                protected void initChannel(Channel channel) throws Exception {
                    System.out.println("S - Channel connected: " + channel);

                    channel.pipeline().addLast(new SimpleChannelInboundHandler<ByteBuf>() {

                        @Override
                        protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
                            System.out.println("S - read: " + msg.toString(StandardCharsets.UTF_8));
                        }
                    });
                }
            })
            .bind(6666).sync();
}

private static void runClient() throws Exception {
    new Bootstrap()
        .group(EVENT_LOOP_GROUP)
        .channel(NioSocketChannel.class)
        .handler(new ChannelInitializer<Channel>() {

            @Override
            protected void initChannel(Channel channel) throws Exception {
                System.out.println("C - Initilized client");

                channel.pipeline().addLast(new SimpleChannelInboundHandler<ByteBuf>() {

                    @Override
                    public void channelActive(ChannelHandlerContext ctx) throws Exception {
                        super.channelActive(ctx);
                        System.out.println("C - write: Hey this is a test message enjoy!");
                        ctx.writeAndFlush(Unpooled.copiedBuffer("Hey this is a test message enjoy!".getBytes(StandardCharsets.UTF_8)));
                    }

                    @Override
                    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { }
                });
            }
        })
        .connect("localhost", 6666).sync();
}

public static void main(String[] args) throws Exception {
    runServer().addListener(future -> {
        runClient();
    });
}
我还用一个单线程eventloopgroup尝试了这个例子,它也工作得很好,但是抛出了一个不影响程序功能的错误。如果这段代码可以正常工作,您可能应该检查您的代码,并尝试在本例中确定代码的方向(请不要像我在本例中所做的那样为您的实际项目创建内联ChannelHandler)