使用JAVA写了一个程序做为客户端,用软件创建一个服务端,可以正常接收数据。但是连接非本地的ip端口的时候,程序连接成功的,就是监听不到任何数据。,但是用软件客户端连接这个非本地ip端口 可以接收到数据 ,这是为什么,大家有遇到过这种问题吗
package com.vcom.iec104.client;
import com.vcom.config.IEC104Config;
import com.vcom.config.OpProperties;
import com.vcom.config.TaskConfig;
import lombok.extern.slf4j.Slf4j;
import org.openmuc.j60870.ClientConnectionBuilder;
import org.openmuc.j60870.Connection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.net.InetAddress;
import java.util.concurrent.TimeUnit;
/**
* IEC104 启动类
*/
@Component
@Slf4j
public class J60870Client implements Runnable {
//监听类
private J60870ClientListener2404 listener2404;
private J60870ClientListener2405 listener2405;
private J60870ClientListener2406 listener2406;
private J60870ClientListener2407 listener2407;
private J60870ClientListener2408 listener2408;
@Autowired
private IEC104Config cfg;
//连接类
private Connection connection;
//连接参数
private ClientConnectionBuilder clientConnectionBuilder;
private volatile boolean running = true;
private static final int MAX_RETRY = 5;
private static final long MAX_BACKOFF = 10000; // 设置最大重试间隔为10秒
private static final String ip = "";
private static final Integer[] ports = {2404,2405,2406,2407,2408};
public J60870Client() {
if (!TaskConfig.isEnableIEC()){
return;
}
try {
//获取server端、从站的ip地址对象,这里使用本地ip
InetAddress address = InetAddress.getByName(ip);
//创建连接参数对象
clientConnectionBuilder = new ClientConnectionBuilder(address);
//设置socket的连接超时时间
clientConnectionBuilder.setConnectionTimeout(60000);
for (int i = 0; i < ports.length; i++) {
if (!establishConnectionForPort(ports[i])) {
// 所有重试失败后,可以选择在此处记录或处理
log.error("所有重试失败,无法连接端口: {}", ports[i]);
// 可能需要考虑是否继续尝试其他端口,或者直接退出循环
} else {
log.info("启动IEC104端口:{}", ports[i]);
}
}
} catch (Exception e) {
log.error("初始化 J60870 客户端失败: {}", e.getMessage());
throw new RuntimeException("初始化 J60870 客户端失败", e);
}
}
private boolean establishConnectionForPort(Integer port) {
clientConnectionBuilder.setPort(port);
for (int retryCount = 0; running && retryCount < MAX_RETRY; retryCount++) {
try {
connection = clientConnectionBuilder.build();
//区分监听数据
switch (port){
case 2404:
listener2404 = new J60870ClientListener2404();
connection.startDataTransfer(listener2404);
break;
case 2405:
listener2405 = new J60870ClientListener2405();
connection.startDataTransfer(listener2405);
break;
case 2406:
listener2406 = new J60870ClientListener2406();
connection.startDataTransfer(listener2406);
break;
case 2407:
listener2407 = new J60870ClientListener2407();
connection.startDataTransfer(listener2407);
break;
case 2408:
listener2408 = new J60870ClientListener2408();
connection.startDataTransfer(listener2408);
break;
}
log.info("连接到端口 {} 成功!", port);
return true; // 连接成功
} catch (IOException e) {
log.error("连接到端口 {} 异常: {}", port, e.getMessage());
if (!retryWithBackoff(retryCount, port)) {
// 如果重试策略决定停止重试,则返回false
return false;
}
}
}
return false; // 所有重试均失败
}
private boolean retryWithBackoff(int retryCount, Integer port) {
long backoff = calculateBackoff(retryCount);
if (backoff > MAX_BACKOFF) {
backoff = MAX_BACKOFF; // 限制最大重试间隔
}
log.info("端口 {} 将在 {} 秒后重试连接...", port, TimeUnit.MILLISECONDS.toSeconds(backoff));
try {
Thread.sleep(backoff);
} catch (InterruptedException ex) {
log.error("连接到端口 {} 的重试线程被中断", port, ex);
Thread.currentThread().interrupt(); // 保留中断状态
return false; // 停止重试
}
return true; // 继续重试
}
private long calculateBackoff(int retryCount) {
return Math.min((long) Math.pow(2, retryCount) * 1000, MAX_BACKOFF); // 指数退避,限制最大值
}
//关闭连接
public void disconnect() {
running = false;
try {
if (connection != null) {
connection.close();
log.info("关闭104连接成功");
}
} catch (Exception e) {
log.error("关闭连接时发生异常: {}", e.getMessage());
}
}
@Override
public void run() {
}
}