Ten wpis jest kontynuacją i uzupełnieniem artykułu: Serwer www na dynamicznym IP
Mamy do rozwiązania następujące problemy:
Musimy napisać program, który:

  • wykrywa zmianę IP serwera
  • informuje OVH o zmianie IP
  • automatycznie ‘przeciska się’ przez okienko logowania OVH
Klasa
package mydynserv;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;

public class MyDynServ1 {
    public static void main(String[] args) {
        //-
        String localhost = null;
        try {
            localhost = Inet4Address.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            Logger.getLogger(MyDynServ1.class.getName()).log(Level.ALL, e.getLocalizedMessage());

        }
        System.out.println("Local IP Address: " + localhost);
        String oldip = null;
        try {
            oldip = Inet4Address.getByName("ematma.com").getHostAddress();
        } catch (UnknownHostException e) {
            Logger.getLogger(MyDynServ1.class.getName()).log(Level.ALL, e.getLocalizedMessage());
        }
        System.out.println("Public IP Address (old): " + oldip);
        String newip = null;
        try {            
            URL url =  new URL("https://api6.ipify.org/?format=text&callback=getIP");
            BufferedReader sc =
                    new BufferedReader(new InputStreamReader(url.openStream()));
            newip = sc.readLine().trim();
        } catch (Exception e) {
            Logger.getLogger(MyDynServ1.class.getName()).log(Level.ALL, e.getLocalizedMessage());
        }
        System.out.println("Public IP Address (new): " + newip);
        if (!oldip.equals(newip)) {
            URL url2 = null;
            HttpURLConnection huc = null;
            String userName = "ematma.com-aria";
            char[] chars = "password".toCharArray();
            try {
                url2 = new URL("https://www.ovh.com/nic/update?system=dyndns&hostname=ematma.com&myip=" + newip);
                huc = (HttpURLConnection) url2.openConnection();
                huc.setAuthenticator(new Authenticator() {
                    @Override
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(userName, chars);
                    }
                });
                System.out.println(huc.getResponseCode());
                System.out.println(huc.getResponseMessage());
            } catch (IOException e) {
                Logger.getLogger(MyDynServ1.class.getName()).log(Level.ALL, e.getLocalizedMessage());
            }
        }
    }
}

Otrzymujesz informację o starym i nowym (zmienionym) nr IP. Nowy nr IP jest automatycznie wpisywany w rekordzie DynHost.
Jeżeli ‘old’ i ‘new’ są jednakowe – numer serwera (rutera) się nie zmienił i nie ma potrzeby zmiany w OVH.
Jeżeli klasa zostanie uruchomiona dwa razy w zbyt krótkim okresie (wyznaczanym przez OVH) numer ‘old’ może być powtórzony na konsoli (tak jakby się nie zmienił), mimo że w OVH został już zmieniony. To nie jest wada klasy lecz blokada przez sesje serwera.
W końcowym pliku warto usunąć wszystkie nieistotne informacje (lokalny IP) i wszystkie użycia System.out.println.
A oto nasza klasa w wersji minimalnej:

package mydynserv;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;

public class MyDynServ2 {
    public static void main(String[] args) {        
        String oldip = null;
        try {
            oldip = Inet4Address.getByName("ematma.com").getHostAddress();
        } catch (UnknownHostException e) {
            Logger.getLogger(MyDynServ2.class.getName()).log(Level.ALL, e.getLocalizedMessage());
        }        
        String newip = null;
        try {
            URL url =  new URL("https://api6.ipify.org/?format=text&callback=getIP");          
            BufferedReader sc =
                    new BufferedReader(new InputStreamReader(url.openStream()));
            newip = sc.readLine().trim();
        } catch (Exception e) {
            Logger.getLogger(MyDynServ2.class.getName()).log(Level.ALL, e.getLocalizedMessage());
        }        
        if (!oldip.equals(newip)) {
            URL url2 = null;
            HttpURLConnection huc = null;
            String userName = "ematma.com-aria";
            char[] chars = ("password").toCharArray();
            try {
                url2 = new URL("https://www.ovh.com/nic/update?system=dyndns&hostname=ematma.com&myip=" + newip);
                huc = (HttpURLConnection) url2.openConnection();
                huc.setAuthenticator(new Authenticator() {
                    @Override
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(userName, chars);
                    }
                });               
                huc.getResponseCode();
                huc.getResponseMessage();
            } catch (IOException e) {
                Logger.getLogger(MyDynServ2.class.getName()).log(Level.ALL, e.getLocalizedMessage());
            }
        }
    }
}

Automatyzacja

Gdy program jest gotowy (klasa działa tak jak powinna) należy
— zapewnić automatyczne, cykliczne uruchamianie powyższego programu
Program można uruchamiać, najlepiej w skrypcie .bat uruchamianym przez harmonogram Windows 7.
Można by też uruchamiać z poziomu Autostartu albo można utworzyć plik .exe odpalany z harmonogramu albo odpalany jako usługa Windows.
Ten program nie musi być stale uruchomiony, a tylko powinien być odpalany od czasu do czasu. W ten sposób można zaoszczędzić pamięć. Ja u siebie uruchamiam plik .java (bez kompilacji) z pliku .bat, uruchamianego co 5 min. przez harmonogram Windows.