heartbeat
This commit is contained in:
parent
62b0cf15bc
commit
260b24975c
|
|
@ -6,7 +6,6 @@ import net.minecraft.commands.Commands;
|
|||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.EventBusSubscriber;
|
||||
import net.neoforged.neoforge.event.RegisterCommandsEvent;
|
||||
import vip.fubuki.playersync.sync.chat.ChatSyncClient;
|
||||
|
||||
@EventBusSubscriber()
|
||||
public class CommandInit {
|
||||
|
|
@ -18,7 +17,6 @@ public class CommandInit {
|
|||
.requires(cs->cs.hasPermission(2))
|
||||
.then(Commands.literal("reconnect")
|
||||
.executes(context -> {
|
||||
new ChatSyncClient().run();
|
||||
// context.getSource().sendSuccess(()->MutableComponent.create(new TranslatableContents("playersync.command.reconnect")),true);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import net.neoforged.fml.config.ModConfig;
|
|||
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.neoforged.neoforge.common.NeoForge;
|
||||
import net.neoforged.neoforge.event.server.ServerStartingEvent;
|
||||
import net.neoforged.neoforge.event.server.ServerStoppingEvent;
|
||||
import org.slf4j.Logger;
|
||||
import vip.fubuki.playersync.config.JdbcConfig;
|
||||
import vip.fubuki.playersync.sync.ChatSync;
|
||||
|
|
@ -179,4 +180,9 @@ public class PlayerSync {
|
|||
LOGGER.info("PlayerSync is ready!");
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onServerStopping(ServerStoppingEvent event){
|
||||
ChatSync.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ public class VanillaSync {
|
|||
File gameDir = Objects.requireNonNull(serverPlayer.getServer()).getServerDirectory().toFile();
|
||||
|
||||
final MinecraftServer server = ServerLifecycleHooks.getCurrentServer();
|
||||
if (server != null && server.isDedicatedServer()) {
|
||||
if (server.isDedicatedServer()) {
|
||||
PlayerSync.LOGGER.debug("Attempting to write dedicated server advancement file");
|
||||
File advancements = new File(gameDir,
|
||||
getSyncWorldForServer() + "/advancements" + "/" + player_uuid + ".json");
|
||||
|
|
|
|||
|
|
@ -8,10 +8,8 @@ import net.neoforged.neoforge.event.entity.player.PlayerEvent;
|
|||
import vip.fubuki.playersync.PlayerSync;
|
||||
import vip.fubuki.playersync.config.JdbcConfig;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.*;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
|
|
@ -26,6 +24,9 @@ public class ChatSyncClient {
|
|||
private static final int RECONNECT_DELAY = 5000;
|
||||
private static final int MAX_RECONNECT_ATTEMPTS = 10;
|
||||
|
||||
private static volatile long lastHeartbeat = System.currentTimeMillis();
|
||||
private static final long HEARTBEAT_INTERVAL = 15000;
|
||||
|
||||
public void run() {
|
||||
int reconnectAttempts = 0;
|
||||
|
||||
|
|
@ -36,40 +37,52 @@ public class ChatSyncClient {
|
|||
JdbcConfig.CHAT_SERVER_PORT.get());
|
||||
|
||||
clientSocket = new Socket();
|
||||
clientSocket.setReuseAddress(true);
|
||||
clientSocket.setKeepAlive(true);
|
||||
clientSocket.setTcpNoDelay(true);
|
||||
|
||||
clientSocket.connect(
|
||||
new InetSocketAddress(
|
||||
JdbcConfig.CHAT_SERVER_IP.get(),
|
||||
JdbcConfig.CHAT_SERVER_PORT.get()
|
||||
),
|
||||
10000
|
||||
15000
|
||||
);
|
||||
|
||||
clientSocket.setSoTimeout(30000);
|
||||
|
||||
out = new PrintWriter(clientSocket.getOutputStream(), true);
|
||||
BufferedReader in = new BufferedReader(
|
||||
new InputStreamReader(clientSocket.getInputStream()));
|
||||
out = new PrintWriter(new BufferedWriter(
|
||||
new OutputStreamWriter(clientSocket.getOutputStream())), true);
|
||||
|
||||
PlayerSync.LOGGER.info("Successfully connected to chat server");
|
||||
reconnectAttempts = 0;
|
||||
lastHeartbeat = System.currentTimeMillis();
|
||||
|
||||
startHeartbeatMonitor();
|
||||
|
||||
BufferedReader in = new BufferedReader(
|
||||
new InputStreamReader(clientSocket.getInputStream()));
|
||||
|
||||
String serverMessage;
|
||||
while (running && (serverMessage = in.readLine()) != null) {
|
||||
lastHeartbeat = System.currentTimeMillis();
|
||||
|
||||
if ("<heartbeat>".equals(serverMessage)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
PlayerSync.LOGGER.info("Received message from chat server: " + serverMessage);
|
||||
Component textComponents = Component.nullToEmpty(serverMessage);
|
||||
if(playerList != null){
|
||||
if (playerList.getServer().isSameThread()) {
|
||||
playerList.broadcastSystemMessage(textComponents, false);
|
||||
} else {
|
||||
playerList.getServer().execute(() ->
|
||||
playerList.broadcastSystemMessage(textComponents, false));
|
||||
}
|
||||
playerList.getServer().execute(() ->
|
||||
playerList.broadcastSystemMessage(textComponents, false));
|
||||
}
|
||||
}
|
||||
|
||||
} catch (SocketTimeoutException e) {
|
||||
PlayerSync.LOGGER.warn("Chat server connection timeout, reconnecting...");
|
||||
PlayerSync.LOGGER.warn("Chat server read timeout, reconnecting...");
|
||||
} catch (ConnectException e) {
|
||||
PlayerSync.LOGGER.warn("Cannot connect to chat server: {}", e.getMessage());
|
||||
} catch (IOException e) {
|
||||
PlayerSync.LOGGER.error("Chat client connection error: {}", e.getMessage());
|
||||
} finally {
|
||||
|
|
@ -82,17 +95,40 @@ public class ChatSyncClient {
|
|||
reconnectAttempts, MAX_RECONNECT_ATTEMPTS);
|
||||
|
||||
try {
|
||||
Thread.sleep(RECONNECT_DELAY);
|
||||
long delay = Math.min(RECONNECT_DELAY * (long)Math.pow(2, reconnectAttempts-1), 60000);
|
||||
Thread.sleep(delay);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
|
||||
PlayerSync.LOGGER.error("Failed to connect to chat server after {} attempts", MAX_RECONNECT_ATTEMPTS);
|
||||
}
|
||||
private void startHeartbeatMonitor() {
|
||||
Thread heartbeatThread = new Thread(() -> {
|
||||
while (running && clientSocket != null && !clientSocket.isClosed()) {
|
||||
try {
|
||||
Thread.sleep(10000); // 每10秒检查一次
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
if (now - lastHeartbeat > HEARTBEAT_INTERVAL) {
|
||||
PlayerSync.LOGGER.warn("No heartbeat for {}ms, sending test message",
|
||||
now - lastHeartbeat);
|
||||
|
||||
// 发送测试消息检查连接
|
||||
if (out != null) {
|
||||
out.println("<heartbeat>");
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, "ChatSync-Heartbeat");
|
||||
heartbeatThread.setDaemon(true);
|
||||
heartbeatThread.start();
|
||||
}
|
||||
|
||||
private void closeConnection() {
|
||||
|
|
|
|||
|
|
@ -3,10 +3,7 @@ package vip.fubuki.playersync.sync.chat;
|
|||
import vip.fubuki.playersync.PlayerSync;
|
||||
import vip.fubuki.playersync.config.JdbcConfig;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.*;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
|
|
@ -29,6 +26,8 @@ public class ChatSyncServer {
|
|||
serverSocket.setReuseAddress(true);
|
||||
PlayerSync.LOGGER.info("Chat server started successfully on port {}", JdbcConfig.CHAT_SERVER_PORT.get());
|
||||
|
||||
startHeartbeatBroadcast();
|
||||
|
||||
while (running && !Thread.currentThread().isInterrupted()) {
|
||||
try {
|
||||
Socket newSocket = serverSocket.accept();
|
||||
|
|
@ -97,6 +96,47 @@ public class ChatSyncServer {
|
|||
}
|
||||
}
|
||||
|
||||
private void startHeartbeatBroadcast() {
|
||||
Thread heartbeatThread = new Thread(() -> {
|
||||
while (running) {
|
||||
try {
|
||||
Thread.sleep(20000);
|
||||
broadcastHeartbeat();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, "ChatSync-Server-Heartbeat");
|
||||
heartbeatThread.setDaemon(true);
|
||||
heartbeatThread.start();
|
||||
}
|
||||
|
||||
private void broadcastHeartbeat() {
|
||||
Iterator<Socket> iterator = SocketList.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Socket socket = iterator.next();
|
||||
if (!socket.isClosed()) {
|
||||
try {
|
||||
PrintWriter writer = new PrintWriter(
|
||||
new BufferedWriter(
|
||||
new OutputStreamWriter(socket.getOutputStream())), true);
|
||||
writer.println("<heartbeat>");
|
||||
} catch (IOException e) {
|
||||
PlayerSync.LOGGER.warn("Failed to send heartbeat to client, removing: {}", e.getMessage());
|
||||
iterator.remove();
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException ex) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
} else {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
running = false;
|
||||
try {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user