diff --git a/pom.xml b/pom.xml
index 83b9dab..37c366a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,5 +33,11 @@
okhttp
4.9.3
+
+
+ io.netty
+ netty-all
+ 4.1.68.Final
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 83b9dab..37c366a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,5 +33,11 @@
okhttp
4.9.3
+
+
+ io.netty
+ netty-all
+ 4.1.68.Final
+
\ No newline at end of file
diff --git a/src/main/java/com/casic/swing/ui/TimeGuardNtp.form b/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
index ce81e35..3bf4535 100644
--- a/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
+++ b/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
@@ -44,7 +44,7 @@
-
+
@@ -55,7 +55,7 @@
-
+
@@ -87,20 +87,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -133,7 +119,7 @@
-
+
@@ -153,7 +139,7 @@
-
+
@@ -163,7 +149,7 @@
-
+
@@ -173,7 +159,7 @@
-
+
@@ -181,6 +167,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
index 83b9dab..37c366a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,5 +33,11 @@
okhttp
4.9.3
+
+
+ io.netty
+ netty-all
+ 4.1.68.Final
+
\ No newline at end of file
diff --git a/src/main/java/com/casic/swing/ui/TimeGuardNtp.form b/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
index ce81e35..3bf4535 100644
--- a/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
+++ b/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
@@ -44,7 +44,7 @@
-
+
@@ -55,7 +55,7 @@
-
+
@@ -87,20 +87,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -133,7 +119,7 @@
-
+
@@ -153,7 +139,7 @@
-
+
@@ -163,7 +149,7 @@
-
+
@@ -173,7 +159,7 @@
-
+
@@ -181,6 +167,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/casic/swing/ui/TimeGuardNtp.java b/src/main/java/com/casic/swing/ui/TimeGuardNtp.java
index 99913c8..aebd36e 100644
--- a/src/main/java/com/casic/swing/ui/TimeGuardNtp.java
+++ b/src/main/java/com/casic/swing/ui/TimeGuardNtp.java
@@ -4,6 +4,12 @@
import com.alibaba.fastjson.JSONObject;
import com.casic.swing.utils.*;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.*;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.DatagramPacket;
+import io.netty.channel.socket.nio.NioDatagramChannel;
+import io.netty.util.CharsetUtil;
import okhttp3.Request;
import javax.swing.*;
@@ -11,6 +17,7 @@
import java.net.InetAddress;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -28,12 +35,16 @@
private JComboBox localHostBox;
private JCheckBox autoCheckBox;
private JButton updateTimeButton;
+ private JLabel udpPortLabel;
+ private JLabel udpPortTitle;
- private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(
- 1, new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build());
+ private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build());
+ private ScheduledFuture future;
private boolean hasNtp = false;
private final String serverConfig;
+ private boolean isTaskRunning = false;
+
public static void main(String[] args) {
new TimeGuardNtp();
}
@@ -48,9 +59,9 @@
setLocationRelativeTo(null);
setVisible(true);
stateView.setText("未同步");
+ recentlyTimeLabel.setText("无法确定最近同步时间");
setStateView(Color.GRAY);
- ConfigHelper.saveConfig();
//检查环境
new SwingWorker() {
@@ -71,35 +82,17 @@
}
}.execute();
+ // 获取后台地址的配置
serverConfig = ConfigHelper.getConfigData();
- /**
- * 时间间隔,单位为毫秒
- * */
- currentTimeLabel.setForeground(Color.BLUE);
- new Timer(1000, e -> {
- String systemTime = TimeOrDateUtil.timestampToTime();
- currentTimeLabel.setText(systemTime);
- }).start();
- String ntpTime = LogToFile.load();
- if (!"".equals(ntpTime)) {
- recentlyTimeLabel.setText(ntpTime);
- } else {
- recentlyTimeLabel.setText("无法确定最近同步时间");
- }
+ // 每秒更新当前时间
+ updateCurrentTimePerSecond();
- Request request = new Request.Builder().url(serverConfig + Constant.FREQUENCY_URL).build();
- HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
- @Override
- public void onSuccess(String s) {
- frequencyLabel.setText(StringHelper.parseJson(s));
- }
+ // 获取同步时间参数
+ getParamTimeSync();
- @Override
- public void onFailure(Exception e) {
-
- }
- });
+ // 获取监听的udp端口
+ getParamCmdUdpPort();
//初始化JComboBox
List addressList = HttpRequestHelper.localHost();
@@ -107,21 +100,28 @@
localHostBox.addItem(address.getHostAddress());
}
+ // 绑定自动同步复选框事件
autoCheckBox.addActionListener(e -> {
JCheckBox checkBox = (JCheckBox) e.getSource();
if (checkBox.isSelected()) {
updateTimeButton.setEnabled(false);
hostTextField.setEnabled(false);
- /**
- * 开启同步,只能开启一个同步线程
- *
- * scheduleAtFixedRate
- * 是以上一个任务开始的时间计时,period时间过去后,检测上一个任务是否执行完毕
- * 如果上一个任务执行完毕,则当前任务立即执行
- * 如果上一个任务没有执行完毕,则需要等上一个任务执行完毕后立即执行
- * */
- executorService.scheduleAtFixedRate(this::updateView, 0, Integer.parseInt(frequencyLabel.getText()), TimeUnit.MINUTES);
+
+ String host = hostTextField.getText().trim();
+ if (host.isEmpty()) {
+ autoCheckBox.setSelected(false);
+ updateTimeButton.setEnabled(true);
+ hostTextField.setEnabled(true);
+ JOptionPane.showMessageDialog(ntpPanel, "授时中心服务器输入错误,请检查", "Runtime Error", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ // 立即执行一次任务
+ future = executorService.schedule(this::updateView, 1, TimeUnit.SECONDS);
} else {
+ if (null != future) {
+ future.cancel(true);
+ }
updateTimeButton.setEnabled(true);
hostTextField.setEnabled(true);
}
@@ -135,13 +135,29 @@
String host = hostTextField.getText().trim();
if (host.isEmpty()) {
autoCheckBox.setSelected(false);
+ updateTimeButton.setEnabled(true);
+ hostTextField.setEnabled(true);
JOptionPane.showMessageDialog(ntpPanel, "授时中心服务器输入错误,请检查", "Runtime Error", JOptionPane.ERROR_MESSAGE);
return;
}
+
+ if (null != future) {
+ future.cancel(false);
+ }
+
+ // 重新获取同步周期
+ getParamTimeSync();
+
// String result = CommandUtil.simulateNtpResult();
String result = CommandUtil.ntpDate(host);
LogToFile.save(result);
+ // 重新启动定时任务
+ if (autoCheckBox.isSelected() == true) {
+ future = executorService.schedule(this::updateView, Integer.parseInt(frequencyLabel.getText()) * 60 - 5, TimeUnit.SECONDS);
+ }
+
+ // 向后台接口提交ntp同步校时的结果
JSONObject object = new JSONObject();
if ("".equals(result)) {
setStateView(Color.RED);
@@ -184,15 +200,14 @@
.post(HttpRequestHelper.createRequestBody(object.toJSONString()))
.build();
HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
-
@Override
public void onSuccess(String s) {
-
+ System.out.println("保存同步结果成功:" + object.get("deltaTime"));
}
@Override
public void onFailure(Exception e) {
- e.printStackTrace();
+ System.out.println("保存同步结果失败:" + e.getMessage());
}
});
}
@@ -202,4 +217,83 @@
dotPanel.setPreferredSize(new Dimension(15, 15));
dotPanel.setBackground(color);
}
+
+ private void getParamTimeSync() {
+ Request request = new Request.Builder().url(serverConfig + Constant.FREQUENCY_URL).build();
+ HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
+ @Override
+ public void onSuccess(String s) {
+ frequencyLabel.setText(StringHelper.parseJson(s));
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+
+ }
+ });
+ }
+
+ private void getParamCmdUdpPort() {
+ Request request = new Request.Builder().url(serverConfig + Constant.CMD_UDP_PORT).build();
+ HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
+ @Override
+ public void onSuccess(String s) {
+ udpPortLabel.setText(StringHelper.parseJson(s));
+
+ startCmdUdpServer();
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+
+ }
+ });
+ }
+
+ private void updateCurrentTimePerSecond() {
+ // 当前时间字体颜色为蓝色
+ currentTimeLabel.setForeground(Color.BLUE);
+
+ // 每秒更新
+ new Timer(1000, e -> {
+ String systemTime = TimeOrDateUtil.timestampToTime();
+ currentTimeLabel.setText(systemTime);
+ }).start();
+ }
+
+ private void startCmdUdpServer() {
+ EventLoopGroup workerGroup = new NioEventLoopGroup();
+ try {
+ Bootstrap b = new Bootstrap();//
+ b.group(workerGroup).channel(NioDatagramChannel.class)//设置UDP通道
+ .handler(new SimpleChannelInboundHandler() {
+ @Override
+ protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
+ try {
+ DatagramPacket datagramPacket = (DatagramPacket) o;
+ String msg = datagramPacket.content().toString(CharsetUtil.UTF_8);
+
+ if (msg.trim().toUpperCase().equals("SYNC")) {
+ updateView();
+ }
+ } catch (Exception e) {
+ throw e;
+ }
+ }
+ })//初始化处理器
+ .option(ChannelOption.SO_BROADCAST, true);// 支持广播
+
+ // 绑定端口,开始接收进来的连接
+ ChannelFuture f = b.bind(Integer.parseInt(udpPortLabel.getText())).sync();
+
+ udpPortTitle.setText("监听端口[已监听]:");
+
+ //让线程进入wait状态,也就是main线程暂时不会执行到finally里面,nettyserver也持续运行,如果监听到关闭事件,可以优雅的关闭通道和nettyserver
+ f.channel().closeFuture().sync();
+ } catch (Exception e) {
+ // TODO: handle exception
+ System.out.println("Exception:" + e.getMessage());
+ workerGroup.shutdownGracefully();
+ }
+ }
}
diff --git a/pom.xml b/pom.xml
index 83b9dab..37c366a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,5 +33,11 @@
okhttp
4.9.3
+
+
+ io.netty
+ netty-all
+ 4.1.68.Final
+
\ No newline at end of file
diff --git a/src/main/java/com/casic/swing/ui/TimeGuardNtp.form b/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
index ce81e35..3bf4535 100644
--- a/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
+++ b/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
@@ -44,7 +44,7 @@
-
+
@@ -55,7 +55,7 @@
-
+
@@ -87,20 +87,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -133,7 +119,7 @@
-
+
@@ -153,7 +139,7 @@
-
+
@@ -163,7 +149,7 @@
-
+
@@ -173,7 +159,7 @@
-
+
@@ -181,6 +167,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/casic/swing/ui/TimeGuardNtp.java b/src/main/java/com/casic/swing/ui/TimeGuardNtp.java
index 99913c8..aebd36e 100644
--- a/src/main/java/com/casic/swing/ui/TimeGuardNtp.java
+++ b/src/main/java/com/casic/swing/ui/TimeGuardNtp.java
@@ -4,6 +4,12 @@
import com.alibaba.fastjson.JSONObject;
import com.casic.swing.utils.*;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.*;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.DatagramPacket;
+import io.netty.channel.socket.nio.NioDatagramChannel;
+import io.netty.util.CharsetUtil;
import okhttp3.Request;
import javax.swing.*;
@@ -11,6 +17,7 @@
import java.net.InetAddress;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -28,12 +35,16 @@
private JComboBox localHostBox;
private JCheckBox autoCheckBox;
private JButton updateTimeButton;
+ private JLabel udpPortLabel;
+ private JLabel udpPortTitle;
- private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(
- 1, new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build());
+ private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build());
+ private ScheduledFuture future;
private boolean hasNtp = false;
private final String serverConfig;
+ private boolean isTaskRunning = false;
+
public static void main(String[] args) {
new TimeGuardNtp();
}
@@ -48,9 +59,9 @@
setLocationRelativeTo(null);
setVisible(true);
stateView.setText("未同步");
+ recentlyTimeLabel.setText("无法确定最近同步时间");
setStateView(Color.GRAY);
- ConfigHelper.saveConfig();
//检查环境
new SwingWorker() {
@@ -71,35 +82,17 @@
}
}.execute();
+ // 获取后台地址的配置
serverConfig = ConfigHelper.getConfigData();
- /**
- * 时间间隔,单位为毫秒
- * */
- currentTimeLabel.setForeground(Color.BLUE);
- new Timer(1000, e -> {
- String systemTime = TimeOrDateUtil.timestampToTime();
- currentTimeLabel.setText(systemTime);
- }).start();
- String ntpTime = LogToFile.load();
- if (!"".equals(ntpTime)) {
- recentlyTimeLabel.setText(ntpTime);
- } else {
- recentlyTimeLabel.setText("无法确定最近同步时间");
- }
+ // 每秒更新当前时间
+ updateCurrentTimePerSecond();
- Request request = new Request.Builder().url(serverConfig + Constant.FREQUENCY_URL).build();
- HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
- @Override
- public void onSuccess(String s) {
- frequencyLabel.setText(StringHelper.parseJson(s));
- }
+ // 获取同步时间参数
+ getParamTimeSync();
- @Override
- public void onFailure(Exception e) {
-
- }
- });
+ // 获取监听的udp端口
+ getParamCmdUdpPort();
//初始化JComboBox
List addressList = HttpRequestHelper.localHost();
@@ -107,21 +100,28 @@
localHostBox.addItem(address.getHostAddress());
}
+ // 绑定自动同步复选框事件
autoCheckBox.addActionListener(e -> {
JCheckBox checkBox = (JCheckBox) e.getSource();
if (checkBox.isSelected()) {
updateTimeButton.setEnabled(false);
hostTextField.setEnabled(false);
- /**
- * 开启同步,只能开启一个同步线程
- *
- * scheduleAtFixedRate
- * 是以上一个任务开始的时间计时,period时间过去后,检测上一个任务是否执行完毕
- * 如果上一个任务执行完毕,则当前任务立即执行
- * 如果上一个任务没有执行完毕,则需要等上一个任务执行完毕后立即执行
- * */
- executorService.scheduleAtFixedRate(this::updateView, 0, Integer.parseInt(frequencyLabel.getText()), TimeUnit.MINUTES);
+
+ String host = hostTextField.getText().trim();
+ if (host.isEmpty()) {
+ autoCheckBox.setSelected(false);
+ updateTimeButton.setEnabled(true);
+ hostTextField.setEnabled(true);
+ JOptionPane.showMessageDialog(ntpPanel, "授时中心服务器输入错误,请检查", "Runtime Error", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ // 立即执行一次任务
+ future = executorService.schedule(this::updateView, 1, TimeUnit.SECONDS);
} else {
+ if (null != future) {
+ future.cancel(true);
+ }
updateTimeButton.setEnabled(true);
hostTextField.setEnabled(true);
}
@@ -135,13 +135,29 @@
String host = hostTextField.getText().trim();
if (host.isEmpty()) {
autoCheckBox.setSelected(false);
+ updateTimeButton.setEnabled(true);
+ hostTextField.setEnabled(true);
JOptionPane.showMessageDialog(ntpPanel, "授时中心服务器输入错误,请检查", "Runtime Error", JOptionPane.ERROR_MESSAGE);
return;
}
+
+ if (null != future) {
+ future.cancel(false);
+ }
+
+ // 重新获取同步周期
+ getParamTimeSync();
+
// String result = CommandUtil.simulateNtpResult();
String result = CommandUtil.ntpDate(host);
LogToFile.save(result);
+ // 重新启动定时任务
+ if (autoCheckBox.isSelected() == true) {
+ future = executorService.schedule(this::updateView, Integer.parseInt(frequencyLabel.getText()) * 60 - 5, TimeUnit.SECONDS);
+ }
+
+ // 向后台接口提交ntp同步校时的结果
JSONObject object = new JSONObject();
if ("".equals(result)) {
setStateView(Color.RED);
@@ -184,15 +200,14 @@
.post(HttpRequestHelper.createRequestBody(object.toJSONString()))
.build();
HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
-
@Override
public void onSuccess(String s) {
-
+ System.out.println("保存同步结果成功:" + object.get("deltaTime"));
}
@Override
public void onFailure(Exception e) {
- e.printStackTrace();
+ System.out.println("保存同步结果失败:" + e.getMessage());
}
});
}
@@ -202,4 +217,83 @@
dotPanel.setPreferredSize(new Dimension(15, 15));
dotPanel.setBackground(color);
}
+
+ private void getParamTimeSync() {
+ Request request = new Request.Builder().url(serverConfig + Constant.FREQUENCY_URL).build();
+ HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
+ @Override
+ public void onSuccess(String s) {
+ frequencyLabel.setText(StringHelper.parseJson(s));
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+
+ }
+ });
+ }
+
+ private void getParamCmdUdpPort() {
+ Request request = new Request.Builder().url(serverConfig + Constant.CMD_UDP_PORT).build();
+ HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
+ @Override
+ public void onSuccess(String s) {
+ udpPortLabel.setText(StringHelper.parseJson(s));
+
+ startCmdUdpServer();
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+
+ }
+ });
+ }
+
+ private void updateCurrentTimePerSecond() {
+ // 当前时间字体颜色为蓝色
+ currentTimeLabel.setForeground(Color.BLUE);
+
+ // 每秒更新
+ new Timer(1000, e -> {
+ String systemTime = TimeOrDateUtil.timestampToTime();
+ currentTimeLabel.setText(systemTime);
+ }).start();
+ }
+
+ private void startCmdUdpServer() {
+ EventLoopGroup workerGroup = new NioEventLoopGroup();
+ try {
+ Bootstrap b = new Bootstrap();//
+ b.group(workerGroup).channel(NioDatagramChannel.class)//设置UDP通道
+ .handler(new SimpleChannelInboundHandler() {
+ @Override
+ protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
+ try {
+ DatagramPacket datagramPacket = (DatagramPacket) o;
+ String msg = datagramPacket.content().toString(CharsetUtil.UTF_8);
+
+ if (msg.trim().toUpperCase().equals("SYNC")) {
+ updateView();
+ }
+ } catch (Exception e) {
+ throw e;
+ }
+ }
+ })//初始化处理器
+ .option(ChannelOption.SO_BROADCAST, true);// 支持广播
+
+ // 绑定端口,开始接收进来的连接
+ ChannelFuture f = b.bind(Integer.parseInt(udpPortLabel.getText())).sync();
+
+ udpPortTitle.setText("监听端口[已监听]:");
+
+ //让线程进入wait状态,也就是main线程暂时不会执行到finally里面,nettyserver也持续运行,如果监听到关闭事件,可以优雅的关闭通道和nettyserver
+ f.channel().closeFuture().sync();
+ } catch (Exception e) {
+ // TODO: handle exception
+ System.out.println("Exception:" + e.getMessage());
+ workerGroup.shutdownGracefully();
+ }
+ }
}
diff --git a/src/main/java/com/casic/swing/utils/ConfigHelper.java b/src/main/java/com/casic/swing/utils/ConfigHelper.java
index e7dbd11..d8e698f 100644
--- a/src/main/java/com/casic/swing/utils/ConfigHelper.java
+++ b/src/main/java/com/casic/swing/utils/ConfigHelper.java
@@ -6,57 +6,45 @@
* @author Administrator
*/
public class ConfigHelper {
- public static void saveConfig() {
- File rootDir = Constant.intRootDir();
- File configFile = new File(rootDir + File.separator + "config.txt");
- if (!configFile.exists()) {
- try {
- configFile.createNewFile();
- } catch (IOException e) {
- e.printStackTrace();
- }
+ private static void saveConfig(File configFile) {
+ try {
+ FileWriter fileWriter = new FileWriter(configFile);
+ BufferedWriter writer = new BufferedWriter(fileWriter);
+ writer.write(Constant.DEFAULT_BASE_URL);
+ writer.flush();
+ writer.close();
+ } catch (IOException e) {
+ e.printStackTrace();
}
- if (0 == configFile.length() || !configFile.exists()) {
- //写入配置文件
- try {
- FileWriter fileWriter = new FileWriter(configFile);
- BufferedWriter writer = new BufferedWriter(fileWriter);
- writer.write("http://localhost:11410");
- writer.flush();
- writer.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- System.out.println("后台配置路径 ===> " + configFile.getAbsolutePath());
}
public static String getConfigData() {
+ // 返回值
+ StringBuilder data = new StringBuilder();
try {
File rootDir = Constant.intRootDir();
File configFile = new File(rootDir + File.separator + "config.txt");
- if (!configFile.exists()) {
- try {
- configFile.createNewFile();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- InputStreamReader streamReader = new InputStreamReader(new FileInputStream(configFile));
- BufferedReader bufferedReader = new BufferedReader(streamReader);
- StringBuilder data = new StringBuilder();
- String s;
- try {
+ if (configFile.exists() == false) {
+ // 如果之前没有config file,则创建一个并写入默认值
+ configFile.createNewFile();
+ saveConfig(configFile);
+
+ data.append(Constant.DEFAULT_BASE_URL);
+ } else {
+ InputStreamReader streamReader = new InputStreamReader(new FileInputStream(configFile));
+ BufferedReader bufferedReader = new BufferedReader(streamReader);
+
+ // 读取config文件中的内容
+ String s;
while ((s = bufferedReader.readLine()) != null) {
- data.append(s);
+ data.append(s.trim());
}
- return data.toString();
- } catch (IOException e) {
- e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
- return "";
+ finally {
+ return data.toString();
+ }
}
}
diff --git a/pom.xml b/pom.xml
index 83b9dab..37c366a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,5 +33,11 @@
okhttp
4.9.3
+
+
+ io.netty
+ netty-all
+ 4.1.68.Final
+
\ No newline at end of file
diff --git a/src/main/java/com/casic/swing/ui/TimeGuardNtp.form b/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
index ce81e35..3bf4535 100644
--- a/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
+++ b/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
@@ -44,7 +44,7 @@
-
+
@@ -55,7 +55,7 @@
-
+
@@ -87,20 +87,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -133,7 +119,7 @@
-
+
@@ -153,7 +139,7 @@
-
+
@@ -163,7 +149,7 @@
-
+
@@ -173,7 +159,7 @@
-
+
@@ -181,6 +167,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/casic/swing/ui/TimeGuardNtp.java b/src/main/java/com/casic/swing/ui/TimeGuardNtp.java
index 99913c8..aebd36e 100644
--- a/src/main/java/com/casic/swing/ui/TimeGuardNtp.java
+++ b/src/main/java/com/casic/swing/ui/TimeGuardNtp.java
@@ -4,6 +4,12 @@
import com.alibaba.fastjson.JSONObject;
import com.casic.swing.utils.*;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.*;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.DatagramPacket;
+import io.netty.channel.socket.nio.NioDatagramChannel;
+import io.netty.util.CharsetUtil;
import okhttp3.Request;
import javax.swing.*;
@@ -11,6 +17,7 @@
import java.net.InetAddress;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -28,12 +35,16 @@
private JComboBox localHostBox;
private JCheckBox autoCheckBox;
private JButton updateTimeButton;
+ private JLabel udpPortLabel;
+ private JLabel udpPortTitle;
- private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(
- 1, new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build());
+ private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build());
+ private ScheduledFuture future;
private boolean hasNtp = false;
private final String serverConfig;
+ private boolean isTaskRunning = false;
+
public static void main(String[] args) {
new TimeGuardNtp();
}
@@ -48,9 +59,9 @@
setLocationRelativeTo(null);
setVisible(true);
stateView.setText("未同步");
+ recentlyTimeLabel.setText("无法确定最近同步时间");
setStateView(Color.GRAY);
- ConfigHelper.saveConfig();
//检查环境
new SwingWorker() {
@@ -71,35 +82,17 @@
}
}.execute();
+ // 获取后台地址的配置
serverConfig = ConfigHelper.getConfigData();
- /**
- * 时间间隔,单位为毫秒
- * */
- currentTimeLabel.setForeground(Color.BLUE);
- new Timer(1000, e -> {
- String systemTime = TimeOrDateUtil.timestampToTime();
- currentTimeLabel.setText(systemTime);
- }).start();
- String ntpTime = LogToFile.load();
- if (!"".equals(ntpTime)) {
- recentlyTimeLabel.setText(ntpTime);
- } else {
- recentlyTimeLabel.setText("无法确定最近同步时间");
- }
+ // 每秒更新当前时间
+ updateCurrentTimePerSecond();
- Request request = new Request.Builder().url(serverConfig + Constant.FREQUENCY_URL).build();
- HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
- @Override
- public void onSuccess(String s) {
- frequencyLabel.setText(StringHelper.parseJson(s));
- }
+ // 获取同步时间参数
+ getParamTimeSync();
- @Override
- public void onFailure(Exception e) {
-
- }
- });
+ // 获取监听的udp端口
+ getParamCmdUdpPort();
//初始化JComboBox
List addressList = HttpRequestHelper.localHost();
@@ -107,21 +100,28 @@
localHostBox.addItem(address.getHostAddress());
}
+ // 绑定自动同步复选框事件
autoCheckBox.addActionListener(e -> {
JCheckBox checkBox = (JCheckBox) e.getSource();
if (checkBox.isSelected()) {
updateTimeButton.setEnabled(false);
hostTextField.setEnabled(false);
- /**
- * 开启同步,只能开启一个同步线程
- *
- * scheduleAtFixedRate
- * 是以上一个任务开始的时间计时,period时间过去后,检测上一个任务是否执行完毕
- * 如果上一个任务执行完毕,则当前任务立即执行
- * 如果上一个任务没有执行完毕,则需要等上一个任务执行完毕后立即执行
- * */
- executorService.scheduleAtFixedRate(this::updateView, 0, Integer.parseInt(frequencyLabel.getText()), TimeUnit.MINUTES);
+
+ String host = hostTextField.getText().trim();
+ if (host.isEmpty()) {
+ autoCheckBox.setSelected(false);
+ updateTimeButton.setEnabled(true);
+ hostTextField.setEnabled(true);
+ JOptionPane.showMessageDialog(ntpPanel, "授时中心服务器输入错误,请检查", "Runtime Error", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ // 立即执行一次任务
+ future = executorService.schedule(this::updateView, 1, TimeUnit.SECONDS);
} else {
+ if (null != future) {
+ future.cancel(true);
+ }
updateTimeButton.setEnabled(true);
hostTextField.setEnabled(true);
}
@@ -135,13 +135,29 @@
String host = hostTextField.getText().trim();
if (host.isEmpty()) {
autoCheckBox.setSelected(false);
+ updateTimeButton.setEnabled(true);
+ hostTextField.setEnabled(true);
JOptionPane.showMessageDialog(ntpPanel, "授时中心服务器输入错误,请检查", "Runtime Error", JOptionPane.ERROR_MESSAGE);
return;
}
+
+ if (null != future) {
+ future.cancel(false);
+ }
+
+ // 重新获取同步周期
+ getParamTimeSync();
+
// String result = CommandUtil.simulateNtpResult();
String result = CommandUtil.ntpDate(host);
LogToFile.save(result);
+ // 重新启动定时任务
+ if (autoCheckBox.isSelected() == true) {
+ future = executorService.schedule(this::updateView, Integer.parseInt(frequencyLabel.getText()) * 60 - 5, TimeUnit.SECONDS);
+ }
+
+ // 向后台接口提交ntp同步校时的结果
JSONObject object = new JSONObject();
if ("".equals(result)) {
setStateView(Color.RED);
@@ -184,15 +200,14 @@
.post(HttpRequestHelper.createRequestBody(object.toJSONString()))
.build();
HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
-
@Override
public void onSuccess(String s) {
-
+ System.out.println("保存同步结果成功:" + object.get("deltaTime"));
}
@Override
public void onFailure(Exception e) {
- e.printStackTrace();
+ System.out.println("保存同步结果失败:" + e.getMessage());
}
});
}
@@ -202,4 +217,83 @@
dotPanel.setPreferredSize(new Dimension(15, 15));
dotPanel.setBackground(color);
}
+
+ private void getParamTimeSync() {
+ Request request = new Request.Builder().url(serverConfig + Constant.FREQUENCY_URL).build();
+ HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
+ @Override
+ public void onSuccess(String s) {
+ frequencyLabel.setText(StringHelper.parseJson(s));
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+
+ }
+ });
+ }
+
+ private void getParamCmdUdpPort() {
+ Request request = new Request.Builder().url(serverConfig + Constant.CMD_UDP_PORT).build();
+ HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
+ @Override
+ public void onSuccess(String s) {
+ udpPortLabel.setText(StringHelper.parseJson(s));
+
+ startCmdUdpServer();
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+
+ }
+ });
+ }
+
+ private void updateCurrentTimePerSecond() {
+ // 当前时间字体颜色为蓝色
+ currentTimeLabel.setForeground(Color.BLUE);
+
+ // 每秒更新
+ new Timer(1000, e -> {
+ String systemTime = TimeOrDateUtil.timestampToTime();
+ currentTimeLabel.setText(systemTime);
+ }).start();
+ }
+
+ private void startCmdUdpServer() {
+ EventLoopGroup workerGroup = new NioEventLoopGroup();
+ try {
+ Bootstrap b = new Bootstrap();//
+ b.group(workerGroup).channel(NioDatagramChannel.class)//设置UDP通道
+ .handler(new SimpleChannelInboundHandler() {
+ @Override
+ protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
+ try {
+ DatagramPacket datagramPacket = (DatagramPacket) o;
+ String msg = datagramPacket.content().toString(CharsetUtil.UTF_8);
+
+ if (msg.trim().toUpperCase().equals("SYNC")) {
+ updateView();
+ }
+ } catch (Exception e) {
+ throw e;
+ }
+ }
+ })//初始化处理器
+ .option(ChannelOption.SO_BROADCAST, true);// 支持广播
+
+ // 绑定端口,开始接收进来的连接
+ ChannelFuture f = b.bind(Integer.parseInt(udpPortLabel.getText())).sync();
+
+ udpPortTitle.setText("监听端口[已监听]:");
+
+ //让线程进入wait状态,也就是main线程暂时不会执行到finally里面,nettyserver也持续运行,如果监听到关闭事件,可以优雅的关闭通道和nettyserver
+ f.channel().closeFuture().sync();
+ } catch (Exception e) {
+ // TODO: handle exception
+ System.out.println("Exception:" + e.getMessage());
+ workerGroup.shutdownGracefully();
+ }
+ }
}
diff --git a/src/main/java/com/casic/swing/utils/ConfigHelper.java b/src/main/java/com/casic/swing/utils/ConfigHelper.java
index e7dbd11..d8e698f 100644
--- a/src/main/java/com/casic/swing/utils/ConfigHelper.java
+++ b/src/main/java/com/casic/swing/utils/ConfigHelper.java
@@ -6,57 +6,45 @@
* @author Administrator
*/
public class ConfigHelper {
- public static void saveConfig() {
- File rootDir = Constant.intRootDir();
- File configFile = new File(rootDir + File.separator + "config.txt");
- if (!configFile.exists()) {
- try {
- configFile.createNewFile();
- } catch (IOException e) {
- e.printStackTrace();
- }
+ private static void saveConfig(File configFile) {
+ try {
+ FileWriter fileWriter = new FileWriter(configFile);
+ BufferedWriter writer = new BufferedWriter(fileWriter);
+ writer.write(Constant.DEFAULT_BASE_URL);
+ writer.flush();
+ writer.close();
+ } catch (IOException e) {
+ e.printStackTrace();
}
- if (0 == configFile.length() || !configFile.exists()) {
- //写入配置文件
- try {
- FileWriter fileWriter = new FileWriter(configFile);
- BufferedWriter writer = new BufferedWriter(fileWriter);
- writer.write("http://localhost:11410");
- writer.flush();
- writer.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- System.out.println("后台配置路径 ===> " + configFile.getAbsolutePath());
}
public static String getConfigData() {
+ // 返回值
+ StringBuilder data = new StringBuilder();
try {
File rootDir = Constant.intRootDir();
File configFile = new File(rootDir + File.separator + "config.txt");
- if (!configFile.exists()) {
- try {
- configFile.createNewFile();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- InputStreamReader streamReader = new InputStreamReader(new FileInputStream(configFile));
- BufferedReader bufferedReader = new BufferedReader(streamReader);
- StringBuilder data = new StringBuilder();
- String s;
- try {
+ if (configFile.exists() == false) {
+ // 如果之前没有config file,则创建一个并写入默认值
+ configFile.createNewFile();
+ saveConfig(configFile);
+
+ data.append(Constant.DEFAULT_BASE_URL);
+ } else {
+ InputStreamReader streamReader = new InputStreamReader(new FileInputStream(configFile));
+ BufferedReader bufferedReader = new BufferedReader(streamReader);
+
+ // 读取config文件中的内容
+ String s;
while ((s = bufferedReader.readLine()) != null) {
- data.append(s);
+ data.append(s.trim());
}
- return data.toString();
- } catch (IOException e) {
- e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
- return "";
+ finally {
+ return data.toString();
+ }
}
}
diff --git a/src/main/java/com/casic/swing/utils/Constant.java b/src/main/java/com/casic/swing/utils/Constant.java
index 091f834..b9b076c 100644
--- a/src/main/java/com/casic/swing/utils/Constant.java
+++ b/src/main/java/com/casic/swing/utils/Constant.java
@@ -7,8 +7,11 @@
*/
public class Constant {
public static final String FREQUENCY_URL = "/config/findSingle?paraName=TIME_SYNC";
+ public static final String CMD_UDP_PORT = "/config/findSingle?paraName=CMD_UDP_PORT";
public static final String SYNCHRONIZE_URL = "/ntp/saveResult";
+ public static final String DEFAULT_BASE_URL = "http://111.198.10.15:11410";
+
public static File intRootDir() {
File rootDir = new File(System.getProperty("user.dir") + File.separator + "logs");
if (!rootDir.exists()) {
diff --git a/pom.xml b/pom.xml
index 83b9dab..37c366a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,5 +33,11 @@
okhttp
4.9.3
+
+
+ io.netty
+ netty-all
+ 4.1.68.Final
+
\ No newline at end of file
diff --git a/src/main/java/com/casic/swing/ui/TimeGuardNtp.form b/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
index ce81e35..3bf4535 100644
--- a/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
+++ b/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
@@ -44,7 +44,7 @@
-
+
@@ -55,7 +55,7 @@
-
+
@@ -87,20 +87,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -133,7 +119,7 @@
-
+
@@ -153,7 +139,7 @@
-
+
@@ -163,7 +149,7 @@
-
+
@@ -173,7 +159,7 @@
-
+
@@ -181,6 +167,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/casic/swing/ui/TimeGuardNtp.java b/src/main/java/com/casic/swing/ui/TimeGuardNtp.java
index 99913c8..aebd36e 100644
--- a/src/main/java/com/casic/swing/ui/TimeGuardNtp.java
+++ b/src/main/java/com/casic/swing/ui/TimeGuardNtp.java
@@ -4,6 +4,12 @@
import com.alibaba.fastjson.JSONObject;
import com.casic.swing.utils.*;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.*;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.DatagramPacket;
+import io.netty.channel.socket.nio.NioDatagramChannel;
+import io.netty.util.CharsetUtil;
import okhttp3.Request;
import javax.swing.*;
@@ -11,6 +17,7 @@
import java.net.InetAddress;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -28,12 +35,16 @@
private JComboBox localHostBox;
private JCheckBox autoCheckBox;
private JButton updateTimeButton;
+ private JLabel udpPortLabel;
+ private JLabel udpPortTitle;
- private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(
- 1, new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build());
+ private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build());
+ private ScheduledFuture future;
private boolean hasNtp = false;
private final String serverConfig;
+ private boolean isTaskRunning = false;
+
public static void main(String[] args) {
new TimeGuardNtp();
}
@@ -48,9 +59,9 @@
setLocationRelativeTo(null);
setVisible(true);
stateView.setText("未同步");
+ recentlyTimeLabel.setText("无法确定最近同步时间");
setStateView(Color.GRAY);
- ConfigHelper.saveConfig();
//检查环境
new SwingWorker() {
@@ -71,35 +82,17 @@
}
}.execute();
+ // 获取后台地址的配置
serverConfig = ConfigHelper.getConfigData();
- /**
- * 时间间隔,单位为毫秒
- * */
- currentTimeLabel.setForeground(Color.BLUE);
- new Timer(1000, e -> {
- String systemTime = TimeOrDateUtil.timestampToTime();
- currentTimeLabel.setText(systemTime);
- }).start();
- String ntpTime = LogToFile.load();
- if (!"".equals(ntpTime)) {
- recentlyTimeLabel.setText(ntpTime);
- } else {
- recentlyTimeLabel.setText("无法确定最近同步时间");
- }
+ // 每秒更新当前时间
+ updateCurrentTimePerSecond();
- Request request = new Request.Builder().url(serverConfig + Constant.FREQUENCY_URL).build();
- HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
- @Override
- public void onSuccess(String s) {
- frequencyLabel.setText(StringHelper.parseJson(s));
- }
+ // 获取同步时间参数
+ getParamTimeSync();
- @Override
- public void onFailure(Exception e) {
-
- }
- });
+ // 获取监听的udp端口
+ getParamCmdUdpPort();
//初始化JComboBox
List addressList = HttpRequestHelper.localHost();
@@ -107,21 +100,28 @@
localHostBox.addItem(address.getHostAddress());
}
+ // 绑定自动同步复选框事件
autoCheckBox.addActionListener(e -> {
JCheckBox checkBox = (JCheckBox) e.getSource();
if (checkBox.isSelected()) {
updateTimeButton.setEnabled(false);
hostTextField.setEnabled(false);
- /**
- * 开启同步,只能开启一个同步线程
- *
- * scheduleAtFixedRate
- * 是以上一个任务开始的时间计时,period时间过去后,检测上一个任务是否执行完毕
- * 如果上一个任务执行完毕,则当前任务立即执行
- * 如果上一个任务没有执行完毕,则需要等上一个任务执行完毕后立即执行
- * */
- executorService.scheduleAtFixedRate(this::updateView, 0, Integer.parseInt(frequencyLabel.getText()), TimeUnit.MINUTES);
+
+ String host = hostTextField.getText().trim();
+ if (host.isEmpty()) {
+ autoCheckBox.setSelected(false);
+ updateTimeButton.setEnabled(true);
+ hostTextField.setEnabled(true);
+ JOptionPane.showMessageDialog(ntpPanel, "授时中心服务器输入错误,请检查", "Runtime Error", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ // 立即执行一次任务
+ future = executorService.schedule(this::updateView, 1, TimeUnit.SECONDS);
} else {
+ if (null != future) {
+ future.cancel(true);
+ }
updateTimeButton.setEnabled(true);
hostTextField.setEnabled(true);
}
@@ -135,13 +135,29 @@
String host = hostTextField.getText().trim();
if (host.isEmpty()) {
autoCheckBox.setSelected(false);
+ updateTimeButton.setEnabled(true);
+ hostTextField.setEnabled(true);
JOptionPane.showMessageDialog(ntpPanel, "授时中心服务器输入错误,请检查", "Runtime Error", JOptionPane.ERROR_MESSAGE);
return;
}
+
+ if (null != future) {
+ future.cancel(false);
+ }
+
+ // 重新获取同步周期
+ getParamTimeSync();
+
// String result = CommandUtil.simulateNtpResult();
String result = CommandUtil.ntpDate(host);
LogToFile.save(result);
+ // 重新启动定时任务
+ if (autoCheckBox.isSelected() == true) {
+ future = executorService.schedule(this::updateView, Integer.parseInt(frequencyLabel.getText()) * 60 - 5, TimeUnit.SECONDS);
+ }
+
+ // 向后台接口提交ntp同步校时的结果
JSONObject object = new JSONObject();
if ("".equals(result)) {
setStateView(Color.RED);
@@ -184,15 +200,14 @@
.post(HttpRequestHelper.createRequestBody(object.toJSONString()))
.build();
HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
-
@Override
public void onSuccess(String s) {
-
+ System.out.println("保存同步结果成功:" + object.get("deltaTime"));
}
@Override
public void onFailure(Exception e) {
- e.printStackTrace();
+ System.out.println("保存同步结果失败:" + e.getMessage());
}
});
}
@@ -202,4 +217,83 @@
dotPanel.setPreferredSize(new Dimension(15, 15));
dotPanel.setBackground(color);
}
+
+ private void getParamTimeSync() {
+ Request request = new Request.Builder().url(serverConfig + Constant.FREQUENCY_URL).build();
+ HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
+ @Override
+ public void onSuccess(String s) {
+ frequencyLabel.setText(StringHelper.parseJson(s));
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+
+ }
+ });
+ }
+
+ private void getParamCmdUdpPort() {
+ Request request = new Request.Builder().url(serverConfig + Constant.CMD_UDP_PORT).build();
+ HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
+ @Override
+ public void onSuccess(String s) {
+ udpPortLabel.setText(StringHelper.parseJson(s));
+
+ startCmdUdpServer();
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+
+ }
+ });
+ }
+
+ private void updateCurrentTimePerSecond() {
+ // 当前时间字体颜色为蓝色
+ currentTimeLabel.setForeground(Color.BLUE);
+
+ // 每秒更新
+ new Timer(1000, e -> {
+ String systemTime = TimeOrDateUtil.timestampToTime();
+ currentTimeLabel.setText(systemTime);
+ }).start();
+ }
+
+ private void startCmdUdpServer() {
+ EventLoopGroup workerGroup = new NioEventLoopGroup();
+ try {
+ Bootstrap b = new Bootstrap();//
+ b.group(workerGroup).channel(NioDatagramChannel.class)//设置UDP通道
+ .handler(new SimpleChannelInboundHandler() {
+ @Override
+ protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
+ try {
+ DatagramPacket datagramPacket = (DatagramPacket) o;
+ String msg = datagramPacket.content().toString(CharsetUtil.UTF_8);
+
+ if (msg.trim().toUpperCase().equals("SYNC")) {
+ updateView();
+ }
+ } catch (Exception e) {
+ throw e;
+ }
+ }
+ })//初始化处理器
+ .option(ChannelOption.SO_BROADCAST, true);// 支持广播
+
+ // 绑定端口,开始接收进来的连接
+ ChannelFuture f = b.bind(Integer.parseInt(udpPortLabel.getText())).sync();
+
+ udpPortTitle.setText("监听端口[已监听]:");
+
+ //让线程进入wait状态,也就是main线程暂时不会执行到finally里面,nettyserver也持续运行,如果监听到关闭事件,可以优雅的关闭通道和nettyserver
+ f.channel().closeFuture().sync();
+ } catch (Exception e) {
+ // TODO: handle exception
+ System.out.println("Exception:" + e.getMessage());
+ workerGroup.shutdownGracefully();
+ }
+ }
}
diff --git a/src/main/java/com/casic/swing/utils/ConfigHelper.java b/src/main/java/com/casic/swing/utils/ConfigHelper.java
index e7dbd11..d8e698f 100644
--- a/src/main/java/com/casic/swing/utils/ConfigHelper.java
+++ b/src/main/java/com/casic/swing/utils/ConfigHelper.java
@@ -6,57 +6,45 @@
* @author Administrator
*/
public class ConfigHelper {
- public static void saveConfig() {
- File rootDir = Constant.intRootDir();
- File configFile = new File(rootDir + File.separator + "config.txt");
- if (!configFile.exists()) {
- try {
- configFile.createNewFile();
- } catch (IOException e) {
- e.printStackTrace();
- }
+ private static void saveConfig(File configFile) {
+ try {
+ FileWriter fileWriter = new FileWriter(configFile);
+ BufferedWriter writer = new BufferedWriter(fileWriter);
+ writer.write(Constant.DEFAULT_BASE_URL);
+ writer.flush();
+ writer.close();
+ } catch (IOException e) {
+ e.printStackTrace();
}
- if (0 == configFile.length() || !configFile.exists()) {
- //写入配置文件
- try {
- FileWriter fileWriter = new FileWriter(configFile);
- BufferedWriter writer = new BufferedWriter(fileWriter);
- writer.write("http://localhost:11410");
- writer.flush();
- writer.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- System.out.println("后台配置路径 ===> " + configFile.getAbsolutePath());
}
public static String getConfigData() {
+ // 返回值
+ StringBuilder data = new StringBuilder();
try {
File rootDir = Constant.intRootDir();
File configFile = new File(rootDir + File.separator + "config.txt");
- if (!configFile.exists()) {
- try {
- configFile.createNewFile();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- InputStreamReader streamReader = new InputStreamReader(new FileInputStream(configFile));
- BufferedReader bufferedReader = new BufferedReader(streamReader);
- StringBuilder data = new StringBuilder();
- String s;
- try {
+ if (configFile.exists() == false) {
+ // 如果之前没有config file,则创建一个并写入默认值
+ configFile.createNewFile();
+ saveConfig(configFile);
+
+ data.append(Constant.DEFAULT_BASE_URL);
+ } else {
+ InputStreamReader streamReader = new InputStreamReader(new FileInputStream(configFile));
+ BufferedReader bufferedReader = new BufferedReader(streamReader);
+
+ // 读取config文件中的内容
+ String s;
while ((s = bufferedReader.readLine()) != null) {
- data.append(s);
+ data.append(s.trim());
}
- return data.toString();
- } catch (IOException e) {
- e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
- return "";
+ finally {
+ return data.toString();
+ }
}
}
diff --git a/src/main/java/com/casic/swing/utils/Constant.java b/src/main/java/com/casic/swing/utils/Constant.java
index 091f834..b9b076c 100644
--- a/src/main/java/com/casic/swing/utils/Constant.java
+++ b/src/main/java/com/casic/swing/utils/Constant.java
@@ -7,8 +7,11 @@
*/
public class Constant {
public static final String FREQUENCY_URL = "/config/findSingle?paraName=TIME_SYNC";
+ public static final String CMD_UDP_PORT = "/config/findSingle?paraName=CMD_UDP_PORT";
public static final String SYNCHRONIZE_URL = "/ntp/saveResult";
+ public static final String DEFAULT_BASE_URL = "http://111.198.10.15:11410";
+
public static File intRootDir() {
File rootDir = new File(System.getProperty("user.dir") + File.separator + "logs");
if (!rootDir.exists()) {
diff --git a/src/main/java/com/casic/swing/utils/HttpRequestHelper.java b/src/main/java/com/casic/swing/utils/HttpRequestHelper.java
index 0c6c943..d355e6c 100644
--- a/src/main/java/com/casic/swing/utils/HttpRequestHelper.java
+++ b/src/main/java/com/casic/swing/utils/HttpRequestHelper.java
@@ -19,7 +19,7 @@
*/
public class HttpRequestHelper {
public static RequestBody createRequestBody(String value) {
- return RequestBody.create(MediaType.parse("application/json; charset=utf-8"), value);
+ return RequestBody.Companion.create(value, MediaType.parse("application/json; charset=utf-8"));
}
public static void doHttpRequest(Request request, IHttpCallback httpCallback) {
diff --git a/pom.xml b/pom.xml
index 83b9dab..37c366a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,5 +33,11 @@
okhttp
4.9.3
+
+
+ io.netty
+ netty-all
+ 4.1.68.Final
+
\ No newline at end of file
diff --git a/src/main/java/com/casic/swing/ui/TimeGuardNtp.form b/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
index ce81e35..3bf4535 100644
--- a/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
+++ b/src/main/java/com/casic/swing/ui/TimeGuardNtp.form
@@ -44,7 +44,7 @@
-
+
@@ -55,7 +55,7 @@
-
+
@@ -87,20 +87,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -133,7 +119,7 @@
-
+
@@ -153,7 +139,7 @@
-
+
@@ -163,7 +149,7 @@
-
+
@@ -173,7 +159,7 @@
-
+
@@ -181,6 +167,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/casic/swing/ui/TimeGuardNtp.java b/src/main/java/com/casic/swing/ui/TimeGuardNtp.java
index 99913c8..aebd36e 100644
--- a/src/main/java/com/casic/swing/ui/TimeGuardNtp.java
+++ b/src/main/java/com/casic/swing/ui/TimeGuardNtp.java
@@ -4,6 +4,12 @@
import com.alibaba.fastjson.JSONObject;
import com.casic.swing.utils.*;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.*;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.DatagramPacket;
+import io.netty.channel.socket.nio.NioDatagramChannel;
+import io.netty.util.CharsetUtil;
import okhttp3.Request;
import javax.swing.*;
@@ -11,6 +17,7 @@
import java.net.InetAddress;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -28,12 +35,16 @@
private JComboBox localHostBox;
private JCheckBox autoCheckBox;
private JButton updateTimeButton;
+ private JLabel udpPortLabel;
+ private JLabel udpPortTitle;
- private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(
- 1, new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build());
+ private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build());
+ private ScheduledFuture future;
private boolean hasNtp = false;
private final String serverConfig;
+ private boolean isTaskRunning = false;
+
public static void main(String[] args) {
new TimeGuardNtp();
}
@@ -48,9 +59,9 @@
setLocationRelativeTo(null);
setVisible(true);
stateView.setText("未同步");
+ recentlyTimeLabel.setText("无法确定最近同步时间");
setStateView(Color.GRAY);
- ConfigHelper.saveConfig();
//检查环境
new SwingWorker() {
@@ -71,35 +82,17 @@
}
}.execute();
+ // 获取后台地址的配置
serverConfig = ConfigHelper.getConfigData();
- /**
- * 时间间隔,单位为毫秒
- * */
- currentTimeLabel.setForeground(Color.BLUE);
- new Timer(1000, e -> {
- String systemTime = TimeOrDateUtil.timestampToTime();
- currentTimeLabel.setText(systemTime);
- }).start();
- String ntpTime = LogToFile.load();
- if (!"".equals(ntpTime)) {
- recentlyTimeLabel.setText(ntpTime);
- } else {
- recentlyTimeLabel.setText("无法确定最近同步时间");
- }
+ // 每秒更新当前时间
+ updateCurrentTimePerSecond();
- Request request = new Request.Builder().url(serverConfig + Constant.FREQUENCY_URL).build();
- HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
- @Override
- public void onSuccess(String s) {
- frequencyLabel.setText(StringHelper.parseJson(s));
- }
+ // 获取同步时间参数
+ getParamTimeSync();
- @Override
- public void onFailure(Exception e) {
-
- }
- });
+ // 获取监听的udp端口
+ getParamCmdUdpPort();
//初始化JComboBox
List addressList = HttpRequestHelper.localHost();
@@ -107,21 +100,28 @@
localHostBox.addItem(address.getHostAddress());
}
+ // 绑定自动同步复选框事件
autoCheckBox.addActionListener(e -> {
JCheckBox checkBox = (JCheckBox) e.getSource();
if (checkBox.isSelected()) {
updateTimeButton.setEnabled(false);
hostTextField.setEnabled(false);
- /**
- * 开启同步,只能开启一个同步线程
- *
- * scheduleAtFixedRate
- * 是以上一个任务开始的时间计时,period时间过去后,检测上一个任务是否执行完毕
- * 如果上一个任务执行完毕,则当前任务立即执行
- * 如果上一个任务没有执行完毕,则需要等上一个任务执行完毕后立即执行
- * */
- executorService.scheduleAtFixedRate(this::updateView, 0, Integer.parseInt(frequencyLabel.getText()), TimeUnit.MINUTES);
+
+ String host = hostTextField.getText().trim();
+ if (host.isEmpty()) {
+ autoCheckBox.setSelected(false);
+ updateTimeButton.setEnabled(true);
+ hostTextField.setEnabled(true);
+ JOptionPane.showMessageDialog(ntpPanel, "授时中心服务器输入错误,请检查", "Runtime Error", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ // 立即执行一次任务
+ future = executorService.schedule(this::updateView, 1, TimeUnit.SECONDS);
} else {
+ if (null != future) {
+ future.cancel(true);
+ }
updateTimeButton.setEnabled(true);
hostTextField.setEnabled(true);
}
@@ -135,13 +135,29 @@
String host = hostTextField.getText().trim();
if (host.isEmpty()) {
autoCheckBox.setSelected(false);
+ updateTimeButton.setEnabled(true);
+ hostTextField.setEnabled(true);
JOptionPane.showMessageDialog(ntpPanel, "授时中心服务器输入错误,请检查", "Runtime Error", JOptionPane.ERROR_MESSAGE);
return;
}
+
+ if (null != future) {
+ future.cancel(false);
+ }
+
+ // 重新获取同步周期
+ getParamTimeSync();
+
// String result = CommandUtil.simulateNtpResult();
String result = CommandUtil.ntpDate(host);
LogToFile.save(result);
+ // 重新启动定时任务
+ if (autoCheckBox.isSelected() == true) {
+ future = executorService.schedule(this::updateView, Integer.parseInt(frequencyLabel.getText()) * 60 - 5, TimeUnit.SECONDS);
+ }
+
+ // 向后台接口提交ntp同步校时的结果
JSONObject object = new JSONObject();
if ("".equals(result)) {
setStateView(Color.RED);
@@ -184,15 +200,14 @@
.post(HttpRequestHelper.createRequestBody(object.toJSONString()))
.build();
HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
-
@Override
public void onSuccess(String s) {
-
+ System.out.println("保存同步结果成功:" + object.get("deltaTime"));
}
@Override
public void onFailure(Exception e) {
- e.printStackTrace();
+ System.out.println("保存同步结果失败:" + e.getMessage());
}
});
}
@@ -202,4 +217,83 @@
dotPanel.setPreferredSize(new Dimension(15, 15));
dotPanel.setBackground(color);
}
+
+ private void getParamTimeSync() {
+ Request request = new Request.Builder().url(serverConfig + Constant.FREQUENCY_URL).build();
+ HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
+ @Override
+ public void onSuccess(String s) {
+ frequencyLabel.setText(StringHelper.parseJson(s));
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+
+ }
+ });
+ }
+
+ private void getParamCmdUdpPort() {
+ Request request = new Request.Builder().url(serverConfig + Constant.CMD_UDP_PORT).build();
+ HttpRequestHelper.doHttpRequest(request, new IHttpCallback() {
+ @Override
+ public void onSuccess(String s) {
+ udpPortLabel.setText(StringHelper.parseJson(s));
+
+ startCmdUdpServer();
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+
+ }
+ });
+ }
+
+ private void updateCurrentTimePerSecond() {
+ // 当前时间字体颜色为蓝色
+ currentTimeLabel.setForeground(Color.BLUE);
+
+ // 每秒更新
+ new Timer(1000, e -> {
+ String systemTime = TimeOrDateUtil.timestampToTime();
+ currentTimeLabel.setText(systemTime);
+ }).start();
+ }
+
+ private void startCmdUdpServer() {
+ EventLoopGroup workerGroup = new NioEventLoopGroup();
+ try {
+ Bootstrap b = new Bootstrap();//
+ b.group(workerGroup).channel(NioDatagramChannel.class)//设置UDP通道
+ .handler(new SimpleChannelInboundHandler() {
+ @Override
+ protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
+ try {
+ DatagramPacket datagramPacket = (DatagramPacket) o;
+ String msg = datagramPacket.content().toString(CharsetUtil.UTF_8);
+
+ if (msg.trim().toUpperCase().equals("SYNC")) {
+ updateView();
+ }
+ } catch (Exception e) {
+ throw e;
+ }
+ }
+ })//初始化处理器
+ .option(ChannelOption.SO_BROADCAST, true);// 支持广播
+
+ // 绑定端口,开始接收进来的连接
+ ChannelFuture f = b.bind(Integer.parseInt(udpPortLabel.getText())).sync();
+
+ udpPortTitle.setText("监听端口[已监听]:");
+
+ //让线程进入wait状态,也就是main线程暂时不会执行到finally里面,nettyserver也持续运行,如果监听到关闭事件,可以优雅的关闭通道和nettyserver
+ f.channel().closeFuture().sync();
+ } catch (Exception e) {
+ // TODO: handle exception
+ System.out.println("Exception:" + e.getMessage());
+ workerGroup.shutdownGracefully();
+ }
+ }
}
diff --git a/src/main/java/com/casic/swing/utils/ConfigHelper.java b/src/main/java/com/casic/swing/utils/ConfigHelper.java
index e7dbd11..d8e698f 100644
--- a/src/main/java/com/casic/swing/utils/ConfigHelper.java
+++ b/src/main/java/com/casic/swing/utils/ConfigHelper.java
@@ -6,57 +6,45 @@
* @author Administrator
*/
public class ConfigHelper {
- public static void saveConfig() {
- File rootDir = Constant.intRootDir();
- File configFile = new File(rootDir + File.separator + "config.txt");
- if (!configFile.exists()) {
- try {
- configFile.createNewFile();
- } catch (IOException e) {
- e.printStackTrace();
- }
+ private static void saveConfig(File configFile) {
+ try {
+ FileWriter fileWriter = new FileWriter(configFile);
+ BufferedWriter writer = new BufferedWriter(fileWriter);
+ writer.write(Constant.DEFAULT_BASE_URL);
+ writer.flush();
+ writer.close();
+ } catch (IOException e) {
+ e.printStackTrace();
}
- if (0 == configFile.length() || !configFile.exists()) {
- //写入配置文件
- try {
- FileWriter fileWriter = new FileWriter(configFile);
- BufferedWriter writer = new BufferedWriter(fileWriter);
- writer.write("http://localhost:11410");
- writer.flush();
- writer.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- System.out.println("后台配置路径 ===> " + configFile.getAbsolutePath());
}
public static String getConfigData() {
+ // 返回值
+ StringBuilder data = new StringBuilder();
try {
File rootDir = Constant.intRootDir();
File configFile = new File(rootDir + File.separator + "config.txt");
- if (!configFile.exists()) {
- try {
- configFile.createNewFile();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- InputStreamReader streamReader = new InputStreamReader(new FileInputStream(configFile));
- BufferedReader bufferedReader = new BufferedReader(streamReader);
- StringBuilder data = new StringBuilder();
- String s;
- try {
+ if (configFile.exists() == false) {
+ // 如果之前没有config file,则创建一个并写入默认值
+ configFile.createNewFile();
+ saveConfig(configFile);
+
+ data.append(Constant.DEFAULT_BASE_URL);
+ } else {
+ InputStreamReader streamReader = new InputStreamReader(new FileInputStream(configFile));
+ BufferedReader bufferedReader = new BufferedReader(streamReader);
+
+ // 读取config文件中的内容
+ String s;
while ((s = bufferedReader.readLine()) != null) {
- data.append(s);
+ data.append(s.trim());
}
- return data.toString();
- } catch (IOException e) {
- e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
- return "";
+ finally {
+ return data.toString();
+ }
}
}
diff --git a/src/main/java/com/casic/swing/utils/Constant.java b/src/main/java/com/casic/swing/utils/Constant.java
index 091f834..b9b076c 100644
--- a/src/main/java/com/casic/swing/utils/Constant.java
+++ b/src/main/java/com/casic/swing/utils/Constant.java
@@ -7,8 +7,11 @@
*/
public class Constant {
public static final String FREQUENCY_URL = "/config/findSingle?paraName=TIME_SYNC";
+ public static final String CMD_UDP_PORT = "/config/findSingle?paraName=CMD_UDP_PORT";
public static final String SYNCHRONIZE_URL = "/ntp/saveResult";
+ public static final String DEFAULT_BASE_URL = "http://111.198.10.15:11410";
+
public static File intRootDir() {
File rootDir = new File(System.getProperty("user.dir") + File.separator + "logs");
if (!rootDir.exists()) {
diff --git a/src/main/java/com/casic/swing/utils/HttpRequestHelper.java b/src/main/java/com/casic/swing/utils/HttpRequestHelper.java
index 0c6c943..d355e6c 100644
--- a/src/main/java/com/casic/swing/utils/HttpRequestHelper.java
+++ b/src/main/java/com/casic/swing/utils/HttpRequestHelper.java
@@ -19,7 +19,7 @@
*/
public class HttpRequestHelper {
public static RequestBody createRequestBody(String value) {
- return RequestBody.create(MediaType.parse("application/json; charset=utf-8"), value);
+ return RequestBody.Companion.create(value, MediaType.parse("application/json; charset=utf-8"));
}
public static void doHttpRequest(Request request, IHttpCallback httpCallback) {
diff --git a/src/main/java/com/casic/swing/utils/LogToFile.java b/src/main/java/com/casic/swing/utils/LogToFile.java
index d27cfd0..b050c5a 100644
--- a/src/main/java/com/casic/swing/utils/LogToFile.java
+++ b/src/main/java/com/casic/swing/utils/LogToFile.java
@@ -30,7 +30,7 @@
}
OutputStreamWriter outStream = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
outStream.write(log);
- outStream.write("\r\n");
+// outStream.write("\r\n");
//写入完成关闭流
outStream.close();
} catch (IOException e) {
@@ -43,7 +43,7 @@
File rootDir = Constant.intRootDir();
File logFile = new File(rootDir + File.separator + DATE_FORMAT.format(new Date()) + "_ntp.log");
if (!logFile.exists()) {
- logFile.createNewFile();
+ // logFile.createNewFile();
return "";
}
FileInputStream inputStream = new FileInputStream(logFile);
@@ -59,14 +59,14 @@
return "";
}
//取最后一条记录
- String[] content = data.toString().split("\r\n");
+ String[] content = data.toString().trim().split("\r\n");
String result = content[content.length - 1];
/**
* 5 Jan 11:20:24 ntpdate[807910]: adjust time server 114.118.7.161 offset -0.004064 sec
* 5 Jan 11:24:06 ntpdate[824403]: no server suitable for synchronization found
* */
String ntpDate = result.split("ntpdate")[0];
- String[] split = ntpDate.split(" ");
+ String[] split = ntpDate.trim().split(" ");
Calendar date = Calendar.getInstance();
String year = String.valueOf(date.get(Calendar.YEAR));