通信过程为: (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可以直接接收它,但是看来 失败 。预先感谢任何人的帮助,以下是我代码的基本实现:
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));
}
}
B
在端口6002
上侦听,并在从M1
接收到A
之后,通过在C
之间创建新的信道转发到B
和C
:// 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");
}
});
}
}
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 。非常感谢您能提供帮助!