Karolak Karol
Grupa: I6A1N2
Systemy rozproszone
Projekt:
Aplikacja przesyłająca pliki w sieci
z wykorzystaniem technologii Java RMI
Cel projektu
Celem projektu jest stworzenie aplikacji pozwalającej przesyłać pliki z aplikacji serwera do podłączonych aplikacji klienckich. Aplikacja stworzona ma być z wykorzystaniem technologii Java RMI.
Wymagania
Funkcjonalność aplikacji musi zawierać takie elementy jak:
wyświetlanie na stacji klienta listy plików udostępnianych przez serwer (graficznie lub tekstowo),
odczytywanie udostępnionych plików ze stacji serwera,
zapisywanie pobranych plików na stacji klienta.
Budowa i uruchamianie aplikacji
Budowa aplikacji składa się z następujących etapów:
utworzenie interfejsu opisującego procedury udostępniane przez serwer („IPliki.java”),
utworzenie klasy serwera implementującej interfejs „IPliki” („Server.java”),
utworzenie klasy klienta wywołującej metody udostępniane przez serwer („Client.java”),
kompilacja klas,
uruchomienie rejestru RMI,
uruchomienie aplikacji serwera i klienta.
Opis działania aplikacji
Uruchomienie aplikacji rozpoczyna się od uruchomienia rejestru RMI za pośrednictwem którego będą dokonywane wszystkie operacje pomiędzy serwerem i klientami.
Następnie uruchamiany jest program serwera, który oczekuje na zgłoszenia klientów. Przy uruchamianiu serwera jako parametr można podać ścieżkę katalogu który będzie udostępniony. W przypadku braku parametru udostępniony zostanie katalog bieżący.
Rys. 1 Okno aplikacji serwera
W trakcie działania serwer wyświetla raport z wykonywanych zadań na standardowy urządzenie wyjścia. Raport zawiera numer IP klienta który wywoływał procedurę i zadanie jakie zostało przez niego wykonane.
Uruchomienie aplikacji klienckich wymaga podania adresu IP pod którym aktywny jest program serwera. Jeżeli parametr ten nie zostanie podany to serwer będzie wyszukiwany na maszynie lokalnej. Po uruchomieniu aplikacji klienckiej i uzyskaniu komunikacji z programem serwera na stacji klienkiej pojawia się menu ułatwiające interakcję użytkownika z programem.
Rys. 2 Menu aplikacji klienta
Wybór odpowiedniej cyfry z klawiatury powoduje uruchomienie odpowiadającej jej funkcji. Udostępnione funkcje to: wyświetlanie ścieżki do katalogu udostępnionego na serwerze, zmiana katalogu do którego pobierane będą pliki i pobieranie plików z serwera na stację kliencką. Uruchomienie pobierania plików powoduje wyświetlenie listy plików znajdujących się w udostępnionym katalogu.
Rys. 3 Lista udostępnionych plików
Wybór numeru pliku powoduje jego pobranie z serwera i zapisanie go w wybranym wcześniej katalogu.
Kod programu
IPliki.java
package karolak.sr.rmizal;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.ArrayList;
public interface IPliki extends Remote {
void podlaczenie(String ip) throws RemoteException;
String getUdostepnionyKatalog(String ip) throws RemoteException;
ArrayList getListaPlikow(String ip) throws RemoteException;
Object[] getPlik(String ip, String sciezka) throws RemoteException;
void rozlaczenie(String ip) throws RemoteException;
}
Server.java
package karolak.sr.rmizal;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Server implements IPliki {
private static String udostepnionyKatalog = ".";
public Server() {};
public static void main(String[] args){
udostepnionyKatalog = (args.length < 1 ? getAktualnyKatalog() : args[0]);
try{
Server server = new Server();
IPliki pliki = (IPliki)UnicastRemoteObject.exportObject(server, 0);
Registry registry = LocateRegistry.getRegistry();
registry.bind("IPliki", pliki);
System.out.println("Serwer uruchomiony.");
} catch (Exception ex) {
blad("Błąd serwera: ", ex);
}
}
public void podlaczenie(String ip){
System.out.println("[" + ip + "] Host podlaczony.");
}
public void rozlaczenie(String ip){
System.out.println("[" + ip + "] Host odlaczony.");
}
private static String getAktualnyKatalog(){
String wynik = "";
try{
wynik = new File(".").getCanonicalPath();
} catch (IOException ex) {
blad("Błąd pobierania aktualnego katalogu.", ex);
}
return wynik;
}
private static void blad(String tekst, Exception ex){
System.err.println(tekst + ex.getMessage() + "\n" + ex.toString());
}
public String getUdostepnionyKatalog(String ip) throws RemoteException {
System.out.println("[" + ip + "] Wyslano sciezke udostepnionego katalogu.");
return udostepnionyKatalog;
}
public ArrayList getListaPlikow(String ip) throws RemoteException {
ArrayList wynik = new ArrayList();
File katalog = new File(udostepnionyKatalog);
if (katalog.exists()){
File[] listaPlikow = katalog.listFiles();
for (int i = 0; i < listaPlikow.length; i++){
if (!listaPlikow[i].isDirectory()){
wynik.add(listaPlikow[i].getAbsolutePath());
}
}
} else {
wynik.add(" !!! Udostępniony katalog nie istnieje. !!!");
}
System.out.println("[" + ip + "] Wyslano liste plikow.");
return wynik;
}
public Object[] getPlik(String ip, String sciezka) {
try{
FileInputStream fileInputStream = new FileInputStream(sciezka);
int bajt;
DataInputStream dataInputStream = new DataInputStream(fileInputStream);
ArrayList dane = new ArrayList();
while ((bajt = dataInputStream.read()) != -1){
dane.add(new Integer(bajt));
}
System.out.println("[" + ip + "] Wyslano plik '" + sciezka + "'.");
return dane.toArray();
} catch (FileNotFoundException ex) {
} catch (IOException ex) {
}
return null;
}
}
Client.java
package karolak.sr.rmizal;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;
public class Client {
private Client() {};
public static void main(String[] args) {
String host = (args.length < 1 ? null : args[0]); //null = localhost
String katalogDocelowy = "c:\\";
try {
System.out.println("Klient uruchomiony.");
Registry registry = LocateRegistry.getRegistry(host);
IPliki pliki = (IPliki)registry.lookup("IPliki");
System.out.println("Obiekt pobrany.");
pliki.podlaczenie(getNumerIp());
BufferedReader userIn = new BufferedReader(new InputStreamReader(System.in));
char znak;
wyswietlMenu(katalogDocelowy);
while ((znak = pobierzZnak(userIn)) != '0') {
switch (znak){
case '1':
udostepnionyKatalog(pliki);
break;
case '2':
pobierzPlik(pliki, userIn, katalogDocelowy);
break;
case '3':
katalogDocelowy = zmienKatalogDocelowy(katalogDocelowy, userIn);
break;
default:
System.out.println("Nieprawidlowe polecenie.");
break;
}
wyswietlMenu(katalogDocelowy);
}
System.out.println("Koniec.");
pliki.rozlaczenie(getNumerIp());
} catch (Exception ex) {
blad("Błąd klienta: ", ex);
}
}
private static String zmienKatalogDocelowy(String katalogDocelowy, BufferedReader userIn) {
try{
do {
System.out.println();
System.out.print("Podaj nowy katalog > ");
katalogDocelowy = userIn.readLine();
if (!new File(katalogDocelowy).exists()){
System.out.println();
System.out.println("Wybrany katalog docelowy nie istnieje.");
System.out.println();
} else {
break;
}
} while (true);
} catch (IOException ex){
System.err.println("Blad wyjscia: " + ex.getMessage() + ex.toString());
}
return katalogDocelowy;
}
private static void pobierzPlik(IPliki pliki, BufferedReader userIn, String katalogDocelowy) {
try{
System.out.println();
System.out.println("Lista plikow:");
String numerStr = null;
do {
ArrayList listaPlikow = pliki.getListaPlikow(getNumerIp());
if (numerStr != null){
int numerInt;
try{
numerInt = Integer.parseInt(numerStr);
if (numerInt > listaPlikow.size() || numerInt < 1) {
System.out.println("Nieprawidlowy numer pliku.");
System.out.println();
} else {
String sciezka = (String)listaPlikow.get(numerInt - 1);
System.out.println("Pobieranie pliku '" + sciezka + "'.");
Object[] dane = pliki.getPlik(getNumerIp(), sciezka);
if (dane == null) {
System.out.println("Podany plik nie istnieje.");
System.out.println();
}
String sciezkaDocelowa = katalogDocelowy + sciezka.substring(sciezka.lastIndexOf('\\'));
FileOutputStream fileOutputStream = new FileOutputStream(sciezkaDocelowa, false);
DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream);
for (int i = 0; i < dane.length; i++){
dataOutputStream.write(((Integer)dane[i]).intValue());
}
dataOutputStream.close();
System.out.println("Plik '" + sciezka + "' zostal pobrany do '" + sciezkaDocelowa + "'.");
System.out.println();
}
} catch (NumberFormatException ex) {
System.out.println("Podana wartosc nie jest liczba.");
System.out.println();
} catch (OutOfMemoryError ex) {
System.out.println("Plik jest zbyt duzy.");
System.out.println();
}
}
wyswietlListePlikow(listaPlikow);
} while (!(numerStr = userIn.readLine()).equals("0"));
} catch (RemoteException ex) {
bladPolaczenia(ex);
} catch (IOException ex) {
System.err.println("Blad wyjscia: " + ex.getMessage() + ex.toString());
}
}
private static void wyswietlListePlikow(ArrayList listaPlikow) throws RemoteException {
for (int i = 1; i <= listaPlikow.size(); i++){
System.out.println(i + ". " + listaPlikow.get(i - 1));
}
System.out.println("0. Wyjscie");
System.out.println();
System.out.print("Podaj numer pliku > ");
}
private static void udostepnionyKatalog(IPliki pliki) {
try{
String response = pliki.getUdostepnionyKatalog(getNumerIp());
System.out.println("Udostepniony katalog: " + response);
} catch (RemoteException ex){
bladPolaczenia(ex);
}
}
private static char pobierzZnak(BufferedReader userIn) {
char wynik = (char)0;
try{
String tekst = userIn.readLine();
wynik = tekst.charAt(0);
} catch (IOException ex) {}
return wynik;
}
private static void blad(String tekst, Exception ex){
System.err.println(tekst + ex.getMessage() + "\n" + ex.toString());
}
private static void bladPolaczenia(Exception ex){
blad("Blad polaczenia z serwerem: ", ex);
}
private static void wyswietlMenu(String katalogDocelowy) {
System.out.println();
System.out.println();
System.out.println("=========== System wymiany plikow ===========");
System.out.println("1. Udostepniony katalog");
System.out.println("2. Pobierz plik");
System.out.println("3. Ustaw katalog docelowy (" + katalogDocelowy + ")");
System.out.println("0. Wyjscie");
System.out.println();
System.out.print("Wybierz numer > ");
}
private static String getNumerIp(){
String wynik = "nieznany";
try{
wynik = java.net.InetAddress.getLocalHost().getHostAddress();
} catch (java.net.UnknownHostException ex) { }
return wynik;
}
}
Opis wybranych elementów aplikacji
Poza metodami realizującymi główne zadania aplikacji wykorzystywane są także metody wspomagające działanie aplikacji, np.:
„pobierzZnak” - metoda pobierająca pierwszy znak wprowadzony z klawiatury (wykorzystywana do obsługi menu aplikacji),
„blad” i „bladPolaczenia” - metoda wyświetlająca informacje o błędzie na standardowe wyjście aplikacji,
„getNumerIp” - metoda pobiera numer IP stacji klienckiej.