КДП/Пројекат

Извор: SI Wiki
Пређи на навигацију Пређи на претрагу

KDP projekat nosi 20 bodova, pokriva gradivo sa laboratorijskih vežbi, radi se u Javi 11 i podrazumeva pravljenje distribuiranih programa sa grafičkim interfejsom koji međusobno komuniciraju na jedan od dva načina, Mrežna komunikacija (Socket-i, Mrežno programiranje) ili Remote method invocation (RMI, Udaljeni pozivi procedura). Kako je u oba slučaja moguće da više programa kontaktira jedan drugi program istovremeno, konkurentni deo zadatka se odnosi na to da se takvi slučajevi obrade korektno koristeći neke od sinhronizacionih mehanizama Jave. Sve informacije su samo dodatak ili smernice na ono što je obrađeno na laboratorijskim vežbama tako da se podrazumeva da ste već odgledali snimke/pročitali prezentacije sa laboratorijskih vežbi. Nije potrebno gledati snimke za Mrežnu komunikaciju ako projekat koristi RMI, i obrnuto.

Obično se prave sledeća tri programa:

  • Centralni server — glavni server koji komunicira sa svim podserverima
  • Podserver — serveri koji služe kao posrednik između centralnog servera i korisničkih aplikacija
  • Korisnička aplikacija — komunicira sa podserverima za svoje potrebe

Projekat se brani najkasnije u roku u kome se radi distribuirani deo i on se menja svaka 2 ili više roka, u zavisnosti da li je neko uopšte branio tekući projekat. Moguće je da se pojavi jedan od projekata koji je prethodno bio.

Prethodni projekti i njihova rešenja:

Dozvoljeno je korišćenje eksternih biblioteka.

Informacije

Mrežna komunikacija (java.net)

Овом одељку фале информације. Помозите SI Wiki тако што ћете додати потребне информације.

Remote Method Invocation (java.rmi)

Uspostavljanje međusobne konekcije

Potrebno je samo centralni server upisati u RMI registar. Podserveri i klijentske aplikacije je bolje implementirati preko proširenja UnicastRemoteObject-a kako bi oni dobili anoniman port i time izbegla potreba za pravljenje sistema za usklađivanje slobodnih portova ili ručne promene porta pri pokretanju aplikacija. UnicastRemoteObject-i se mogu preko RMI metode slati drugim aplikacijama i tako uspostaviti konekcija.

public class CentralServer implements CentralServerInterface {
	// ...
    
	public CentralServer(int port, boolean nogui) throws RemoteException {
		// ...
		LocateRegistry.createRegistry(port).rebind("/Central", UnicastRemoteObject.exportObject(this, 0));
		// ...
	}
    
	@Override
	public void addSubserver(SubserverInterface subserver) {	// preko subserver.metodaPodservera(...) možemo da pristupamo udaljenom podserveru
		// ...
		// dodavanje u listu podservera ili neka druga obrada
		// ...
	}
	// ...
}
public class Subserver extends UnicastRemoteObject implements SubserverInterface, Serializable {
	// ...
	private CentralServerInterface centralServer;
	// ...

	private void connectToCentral(String centralHost, int centralPort) {
		// ...
		centralServer = (CentralServerInterface) LocateRegistry.getRegistry(centralHost, centralPort).lookup("/Central");
		centralServer.addSubserver(this, ...);
		// ...
	}
    // ...
}

Greške

Greške rade kako je i očekivano, greške bačene kroz udaljenu proceduru se tretiraju kao da su lokalno bačene.

Greške izazvane prekidima veze

Pored RemoteException, u zavisnosti u kojoj fazi udaljenog poziva se desila greška sa vezom, mogu da se pojave i još neke greške:

  • ConnectException
  • ServerException
  • SocketTimeoutException

Pošto dokumentacija dostupna na internetu nije baš potpuna, moguće je da ni ova lista nije potpuna. Sve ove greške se izvode iz IOException greške.

Timeout

Podrazumevani timeout za RMI je 2 sata, a kako su RMI poziviji blokirajući ovo je nepogodno. Podrazumevani timeout može da se promeni linijom:

System.setProperty("sun.rmi.transport.tcp.responseTimeout", "10000");
public class CentralServer implements CentralServerInterface {
	static {
		System.setProperty("sun.rmi.transport.tcp.responseTimeout", "10000"); // vreme je u milisekundama
		// ...
	}
	// ...
}

Transfer fajlova

Transfer fajlova je moguće odraditi tako što se prvo fajl pretvori u byte niz, pošalje se byte niz preko RMI metode i onda prebaci nazad u fajl na računaru na koji se šalje.

Kako ti fajlovi mogu biti neodređene veličine, potrebno je čitati i slati te fajlove u delovima.

public class CentralServer implements CentralServerInterface {
	// ...

	private void sendFile(String path, int fileID, SubserverInterface subserver) {
		try (InputStream is = new FileInputStream(path)) {
			int readBytes;
			byte[] data = new byte[MAX_SIZE]; // maksimalna količina podataka koja se šalje po jednom pozivu metode, gledati da ne bude toliko velika da prekorači postavljeni timeout
			// MAX_SIZE = 1024 * 1024 * 8 bi značilo da se šalje do 8MB po pozivu metode
			
			while ((readBytes = is.read(data)) != -1) subserver.uploadFile(fileID, data, readBytes);
			
			// zavisi od vaše implementacije, ali ovde bi npr. mogla metoda koja govori da je fajl ceo poslat - subserver.finalizeFile(file);
		} catch (IOException e) {
			// obrada greške, sve RMI greške sa vezom se izvode iz IOException
		}
	}
    // ...
}
public class Subserver extends UnicastRemoteObject implements SubserverInterface, Serializable {
	// ...
	private final HashMap<Integer, String> files = new HashMap<>();	// čuva putanju do fajla u koji se upisuje, ili neku složeniju strukturu po potrebi
	// ...

	@Override
	public void uploadFile(int fileID, byte[] data, int readBytes) {
		// zavisi od zadatka, moguće da će biti potrebna neka sinhronizacija ovde

		try (OutputStream os = new FileOutputStream(files.get(fileID), true)) {
			// prvi parametar FileOutputStream-a je path gde će se fajl nalaziti, drugi paramtetar je da li se dodaje na kraj već postojećeg fajla ili se pravi novi

			os.write(data, 0, readBytes);
		} catch (IOException e) {
			// obrada greške
		}
	}
	// ...
}

Testiranje

Testiranje je najbolje vršiti sa više računara povezanih u istu mrežu. IP adresa programa na koji se vezujete je IPv4 adresa mrežnog interfejsa preko kojeg taj program pristupa mreži. Nju možete naći kucanjem komande ipconfig u Command Prompt-u na računaru na kome je taj program pokrenut.

Alternativno, programski možete doći do nje (mada ova metoda nije 100% sigurna da daje adresu pravog interfejsa) sa sledećom funkcijom:

String ip = InetAddress.getLocalHost().getHostAddress();

Mogući testovi:

  • Naglo gašenje nekog od programa (centralnog servera, podservera, korisničke aplikacije).
  • Vađenje kabla za internet ili gašenje Wi-Fi veze za vreme rada programa.

Ova dva testa treba izvršiti u raznim situacijama u kojima program može da se nađe sa različitim kombinacijama pokrenutih programa na svakom računaru.

Moguće je testirati projekat i u sali P26, samo što se od dežurnog mora zatražiti da se isključi žaštita koja blokira RMI pozive između računara. Nagovestiti da je za KDP projekat, administratori bi trebalo da znaju šta isključuju u tom slučaju. Logovanje na više računara odjednom preko istog naloga ne pravi problem.

Izveštaj

Izveštaj se piše po specifikaciji navedenoj u postavci projekta i predstavlja totalno gubljenje vremena kojeg već nemate.

Kako opis samog formata izveštaja zauzima 50% celog teksta projekta, dostupan je i prazan izveštaj koji možete da popunite.

Za izradu dijagrama može da se koristi StarUML.

Velika je šansa da se na odbrani neće ni ulaziti u izveštaj, ali kako se on šalje uz izvorni kod projekta moguće je da će neko sa predmeta ući u njega i pažljivo ga pročitati.

Odbrana

Odbrana se održava u nekoj računarskih sala fakulteta.

Na odbrani je potrebno da se pokrenu programi na 4 računara odjednom tako da različiti računari komuniciraju međusobno. Projekat se onda prezentuje i demonstrira (uključujući neke situacije pri gubitku veze), a zatim se zadaje neka sitna modifikacija. Pitanja vezana za projekat se odnose na to kako je neki deo implementiran.

Dostupan je pristup internetu.