Java Netty跨渠道通信失败

时间:2020-11-09 15:41:10

标签: java sockets netty nio

我希望实现以下三个方面的沟通: enter image description here

通信过程为: (1)A向B发送M1 (2)B在收到M1之后转发给C (3)C在收到M1之后,以M2响应 (4)B在收到M2后,将M2转发给A (5)最后是输出M2

我已经使用Netty实现了所有代码,但是目前的问题是: B从C接收到M2之后,我尝试将M2放入A和B之间的通信通道,希望A可以直接接收它,但是看来 失败 。预先感谢任何人的帮助,以下是我代码的基本实现:

  1. A.java向B发送M1,而AHandler.java侦听B发送的消息:
// A.java

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

public class A {
    public static void main(String[] args) {
        // loop group
        EventLoopGroup loopGroup = new NioEventLoopGroup();
        // create bootstrap
        Bootstrap bootstrap = new Bootstrap();
        try {
            bootstrap.group(loopGroup)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new AHandler());
                        }
                    });
            ChannelFuture future = bootstrap.connect("localhost", 6002).sync();
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            loopGroup.shutdownGracefully();
        }
    }
}
// AHandler.java

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.util.CharsetUtil;

public class AHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        String M1 = "M1";
        ctx.writeAndFlush(Unpooled.copiedBuffer(M1, CharsetUtil.UTF_8));
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // !!! Hope to receive what B forwards from C, namely M2, but cannot receive it
        ByteBuf buf = (ByteBuf) msg;
        System.out.println("B responds receipt: " + buf.toString(CharsetUtil.UTF_8));
    }
}
  1. B在端口6002上侦听,并在从M1接收到A之后,通过在C之间创建新的信道转发到BC
// B.java

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class B {
    public static void main(String[] args) {
        // create thread pool
        // create Boss group : receiving client connection
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        // create work group: network read and communication
        EventLoopGroup workGroup = new NioEventLoopGroup();
        // create start class
        ServerBootstrap bootstrap = new ServerBootstrap();

        try {
            bootstrap.group(bossGroup, workGroup) // set thread group
                    .channel(NioServerSocketChannel.class) //set channel
                    .option(ChannelOption.SO_BACKLOG, 1024) // set the number of thread connections
                    //.option(ChannelOption.SO_KEEPALIVE, true) // keep connection
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new BHandler());
                        }
                    }).childOption(ChannelOption.SO_KEEPALIVE, true);
            System.out.println("----- B is online -----");
            ChannelFuture channelFuture = bootstrap.bind(6002).sync();
            channelFuture.channel().closeFuture().sync();
        }  catch (Exception e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }
}
 
// BHandler.java (as the server end between A and B)

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.CharsetUtil;
import io.netty.util.concurrent.GlobalEventExecutor;

public class BHandler extends ChannelInboundHandlerAdapter {
    public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    public static Channel Channel_AB = null;

    public void BForwardM1() {
        EventLoopGroup loopGroup = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        try {
            bootstrap.group(loopGroup)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new BCHandler());
                        }
                    });
            ChannelFuture future = bootstrap.connect("localhost", 6003).sync();
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            loopGroup.shutdownGracefully();
        }
    }
    
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // Add channel_AB to channel group
        Channel channel_AB = ctx.channel();
        Channel_AB = channel_AB;
        channelGroup.add(channel_AB);

        System.out.println("Received from A: " + channel_AB.remoteAddress() + ", channel ID: " + channel_AB.id());
        ByteBuf buf = (ByteBuf) msg;
        String M1_From_A = buf.toString(CharsetUtil.UTF_8);
        System.out.println("M1_From_A: " + M1_From_A);
    }
    
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        // B forwards M1 to C
        BForwardM1();
    }

}

// BCHandler.java (as the client end of between B and C)

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.util.CharsetUtil;

public class BCHandler extends ChannelInboundHandlerAdapter{

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        String M1 = "M1";
        // B forwards M1 to C
        ctx.writeAndFlush(Unpooled.copiedBuffer(M1, CharsetUtil.UTF_8));
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        // C responds with M2
        String M2 = buf.toString(CharsetUtil.UTF_8);
        System.out.println("Receive C's respond: " + M2);

        // !!! Trying to put M2 to AB's channel
        BHandler.channelGroup.forEach(ch -> {
            if (ch != null) {
                ch.writeAndFlush(Unpooled.copiedBuffer(M2, CharsetUtil.UTF_8));
            } else {
                System.out.println("No available channel");
            }
        });
    }
}

  1. C侦听端口6003,并用消息B响应M2
// C.java

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class C {

    public static void main(String[] args) {
        // create Boss group : receiving client connection
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        // create work group: network read and communication
        EventLoopGroup workGroup = new NioEventLoopGroup();
        // create start class
        ServerBootstrap bootstrap = new ServerBootstrap();

        try {
            bootstrap.group(bossGroup, workGroup) // set thread group
                    .channel(NioServerSocketChannel.class) //set channel
                    .option(ChannelOption.SO_BACKLOG, 1024) // set the number of thread connections
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new CHandler());
                        }
                    });
            System.out.println("----- C is online -----");
            ChannelFuture channelFuture = bootstrap.bind(6003).sync();
            channelFuture.channel().closeFuture().sync();
        }  catch (Exception e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }

}
// CHandler.java

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;

public class CHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        System.out.println("Receive from B: " + buf.toString(CharsetUtil.UTF_8));
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        // C responds with M2
        ctx.writeAndFlush(Unpooled.copiedBuffer("M2", CharsetUtil.UTF_8));
    }
}

我的想法是将AB channel context传递到BCHandler.java,后者从C接收响应,然后使用AB通道发送回A,< strong>,但看来A最终无法收到M2 。非常感谢您能提供帮助!

1 个答案:

答案 0 :(得分:0)

本质上需要实现的是使用Netty的代理服务器,因此此example可以解决问题,并且对我有用。