netty客户端A在宿主机, B在虚拟机中, 在进行通信时, 出现问题, 如何处理, 问题如下
----------客户端之间通信失败, 正在重连...
失败原因: Connection refused: getsockopt: /192.168.5.91:65492
io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: getsockopt: /192.168.5.91:65492
Caused by: java.net.ConnectException: Connection refused: getsockopt
at java.base/sun.nio.ch.Net.pollConnect(Native Method)
at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:682)
at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:973)
at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:337)
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:339)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:776)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:1583)
netty客户端之间主要连接代码如下:
/**
* 读取服务端发送的数据
* @param ctx
* @param msg
* @throws Exception
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof MessageResult<?> messageResult){
System.out.println("收到服务端"+ ctx.channel().remoteAddress() +"的消息: ");
//tcp请求
if (Objects.equals(messageResult.getType(), MessageConstant.TCP_REQUEST)){
String address = (String) messageResult.getData();
System.out.println("--------新连接的IP为: " + address);
String ip = address.substring(0,address.indexOf(":"));
int port = Integer.parseInt(address.substring(address.indexOf(":") + 1)) ;
System.out.println("-----------正在进行客户端之间的连接...");
// new Thread(new Runnable() {
// @Override
// public void run() {
// nettyClientConnetion.clientConnection(ip, port);
// }
// }).start();
//进行客户端之间的连接
nettyClientConnetion.clientConnection(ip, port);
}else {
System.out.println("Code: " + messageResult.getCode());
System.out.println("type: " + messageResult.getType());
System.out.println("Data: " + messageResult.getData());
}
}else {
System.out.println("收到未知类型的消息:" + msg.getClass().getName());
}
}
-------------------------------------------------------------
@Component
public class NettyClientConnetion {
private EventLoopGroup worker;
private ChannelFuture channelFuture;
public void clientConnection(String ip, int port){
worker = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(worker)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(
// new LoggingHandler(LogLevel.INFO),
new MessageDecoder(),
new MessageEncoder(),
new NettyClientConnectionHandler()
);
}
});
try {
//不需要sync, 否则会阻塞进程, 导致客户端重启
channelFuture = bootstrap.connect(ip, port)
.addListener(new ConnectionClientListener(this, ip, port));
channelFuture.channel().closeFuture().sync();
} catch (Exception e) {
System.err.println("连接过程中出现异常: " + e.getMessage());
}
}
}
--------------------------------------------
//客户端之间连接监听
public class ConnectionClientListener implements ChannelFutureListener {
private final NettyClientConnetion nettyClientConnetion;
private final String ip;
private final int port;
public ConnectionClientListener(NettyClientConnetion nettyClientConnetion, String ip, int port){
this.nettyClientConnetion = nettyClientConnetion;
this.ip = ip;
this.port = port;
}
@Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
if (!channelFuture.isSuccess()){
Throwable cause = channelFuture.cause();
System.err.println("----------客户端之间通信失败, 正在重连...");
System.err.println("失败原因: " + cause.getMessage());
cause.printStackTrace(System.err);
//获取ChannelFuture对应的EventLoop
final EventLoop eventLoop = channelFuture.channel().eventLoop();
eventLoop.schedule(new Runnable() {
@Override
public void run() {
try {
nettyClientConnetion.clientConnection(ip, port);
}catch (Exception e){
throw new RuntimeException(e);
}
}
}, 1L, TimeUnit.SECONDS);
}
}
}