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)); } } }