jNetServer/src/jnet/server/probe/Ping.java

141 lines
5.2 KiB
Java

package jnet.server.probe;
import java.io.IOException;
import java.net.InetAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import jnet.lib.LogFile;
import jnet.lib.Message;
import jnet.lib.Status;
import jnet.lib.object.Event;
import jnet.lib.object.Map;
import jnet.lib.object.MapObject;
import jnet.server.Database;
import jnet.server.Server;
import jnet.server.ServerMessageParser;
public class Ping extends Thread {
// Perioda opakování v sekundách
private static final int PERIOD = 3;
// Timeout pro ping (v milisekundách)
private static final int TIMEOUT = 2000;
// pocet pokus pro nastaveni offline statusu
private static final int ATTEMPT = 3;
public Ping() {
}
@Override
public void start() {
init();
}
private void init() {
// ExecutorService pro paralelní provádění pingů
ExecutorService executorService = Executors.newCachedThreadPool();
// ScheduledExecutorService pro periodické provádění
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
// Naplánování periodického provádění kontrol
scheduledExecutorService.scheduleAtFixedRate(() -> {
for (Map map : Server.maps) {
for (MapObject mo : map.getObjects()) {
if (mo.isActive()) {
// Vytvoření úkolu pro pingování každé IP adresy
executorService.submit(() -> {
try {
long responseTime = pingWithResponseTime(mo.getIp());
if (responseTime >= 0) {
isOnline(mo, responseTime);
} else {
isOffline(mo);
}
} catch (Exception e) {
LogFile.printDebug("Chyba pri pingovani " + mo.getIp() + ": " + e.getMessage());
}
});
}
}
}
}, 0, PERIOD, TimeUnit.SECONDS);
}
// Funkce pro kontrolu dostupnosti IP adresy s timeoutem a zobrazení času odezvy
private static long pingWithResponseTime(String ipAddress) throws IOException, InterruptedException {
InetAddress inet = InetAddress.getByName(ipAddress);
long startTime = System.currentTimeMillis(); // Začátek měření času
boolean reachable = inet.isReachable(TIMEOUT); // Timeout pro ping 5 sekund
long endTime = System.currentTimeMillis(); // Konec měření času
if (reachable) {
return endTime - startTime; // Vrátí dobu odezvy v milisekundách
} else {
return -1; // Pokud není dostupná, vrátí -1
}
}
private void isOnline(MapObject mo, long responseTime) {
// LogFile.printDebug(mo.getName() + "(" + mo.getIp() + ") online, latence: " + responseTime + " ms");
// pokud neni predchozi stav ok odesle novy stav
if (mo.getStatus() != Status.OK) {
// pokud byl predchozi stav offline ukonci event
if (mo.getStatus() == Status.OFFLINE) {
// zapise do logu konec udalosti
Event event = Database.endEvent(mo.getId(), Event.TYPE_PING);
for (int i = 0; i < Server.events.size(); i++) {
if (Server.events.get(i).getId() == event.getId()) {
Server.events.set(i, event);
ServerMessageParser.sendAll(new Message(Message.EVENT_UPDATE, (Event) event));
break;
}
}
// vynuluje počet pokusu o ping
mo.setPingAttemp(0);
// nastavi a odesle stav
setNewState(mo, Status.OK);
}
// pokud byl predchozi stav N/A
if (mo.getStatus() == Status.NA) {
// nastavi a odesle stav
setNewState(mo, Status.OK);
}
}
}
private void setNewState(MapObject mo, int state) {
mo.setStatus(state);
// odesle stav
int[] o = {mo.getId(), state};
ServerMessageParser.sendAll(new Message(Message.STATUS_UPDATE, o));
}
private void isOffline(MapObject mo) {
// zvysi pocet jiz probehlích pokusu o ping
mo.pingAttemp++;
// vyhodnoti
if (mo.getStatus() != Status.OFFLINE && mo.getPingAttemp() >= ATTEMPT) {
int[] o = {mo.getId(), Status.OFFLINE};
// nastavi objektu status
mo.setStatus(Status.OFFLINE);
// zapise do logu
// zapise do databaze
Event event = Database.addEvent(mo.getId(), "offline", Event.TYPE_PING);
Server.events.add(event);
//odesle stav a event klientum
ServerMessageParser.sendAll(new Message(Message.STATUS_UPDATE, o));
ServerMessageParser.sendAll(new Message(Message.EVENT_NEW, event));
}
}
}