gabboraron / orsi-osszefoglalo

osztott rendszerek | server - kliens | FTP | párhuzamosság | RMI | Adatbázis

Home Page:http://kitlei.web.elte.hu/segedanyagok/felev/2018-2019-tavasz/osztott/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Összefoglaló

Tartalom:


Elméleti rész főbb fogalmai

Főbb irányvonalak:

  • Grid
  • Cloud
  • infomrációs rendszerek

Virtualizáció

A hardware -> Interface -> Hardware/software system átalakítja program -> Interface A -> Implementation of mimicking A on B -> Interface B -> Hardware/software system B alakká.

Szerkezete

  • Application
    • Library functions
    • Operating system, sys calls
  • Hardware -> general instructions,Prvileged instructions

Process VM és VM monitor

JAVA

minden bytcode egy "mini program", a runtimeban van futtatva:

  • Application
  • Runtime sys
    • Operating system
  • Hardware

VMware, VirtualBox

  • Applications
    • Operating system
  • Virtual machine monitor
  • Hardware

Előnyei a JAVA féle megoldáshoz képest:

A teljes Application és OS réteget egy teljesen új gépre viheti át. Ekkor a VM Monitor egy operációs rendszer! Azaz nagyon egszerű rendszerekkel rendelkezik, a minimális driverekkel és hasonlókkal, de egy teljes OS tulajdonságaival ugyankkor a minimális tulajdonságokkal amik a feladat végrehajtásához szükségesek.

Tehát közvelten a hardwaerhez van útja a az App és OS rétegnek, hiszen a VMközbvetlen a hardwaret szólítja meg.

USER level és kernel level szálak

stackowerflow

a lényege, hogy az egyiket a processzor szintjén hozzuk létre, a másikat pedig a programnak kiosztott erőforrásokban hozzuk létre

Interaktív program

Olyan program ami felhasználó interakciói nélkül nem műödne, pl MS-Excel, bővebben

mobil IP

Az IPt kiosztó home server újrahosztol

anycast - továbbítja a hozzá kapcsolódó routereknek a csomagot

changeroute - az olvasási pontot átteszi máshova

RPC

Kliens oldal

az interface a paraméterekt becsomagolva elküldi a szervernek

Szerver oldal

megkapja a paramétereket, ugyanazzal a paraméterrel és meghívja az azonos paraméterezésű, azonos nevű progamot

middleware szempontból csak a szerveren a kicsomagols és újraparaméterezés az érdekes

Részletesen:

  • a kliens eljárás meghívja a csatolót
  • a csatoló létrehozza az üzenetet, meghívja a kliens OSét a csatoló egy olyan kódrészlet ami átalakítja a bemeneti kódot a szálításhoz és az OS hívásokhoz
  • a kliens OS elküldi az üzenetet a távoli gép OSére
  • a távoli gép OSe megkapja az üznet és a helyi csatolónak átadja
  • a távoli gépen kicsomagolódik az üzenet és meghívvja a megszólított szervert
  • a szerver elvégzí a szükséges hívásokat és visszatér a kért értékkel
  • a távoli gép OSének csatolójával becsomagolódik a szerver válasza
  • a távoli gép OSe elküldi a kliens OSnek
  • a kliens OS megkapja, és átadja kicsomagolásra a csatolónak
  • kicsomagolódik a válasz a kliensnél és átadja a kliens függvénynek ami a hívást kezdeményezte

Ilyenkor a httérben a szerver és a kliens egy "közös" headert használnak, de a gnerált kód külön-külön a szerveren és a kliensen jelenik meg a helyi (klines/szerver) linkeren keresztül, et a DCE

DCE

Tehát ez olyan, mintha egy köztes gép lenne, ami a szükséges fájlokat tárolja, amikre mindkét oldalnak szükésge van, de gy ilyen felállásban ha a köztes szerver ami a headereket tárolja(Directory server) meghal akkor a rendszer is használhatatlan az új kliensek számára, a régieknél már be van linkelve a szükséges fájl. Részletese menete:

  • Register server endpoint
  • register service from Direcotry server to server
  • Client look up for directory server
  • Client ask for server's endpoint
  • Clinet do RPC

content based routing

ccollections of brokers in a network and let to route the msg to broker to broker

content based broker

don't thell to the broker what the msssg is about and the broke find it out

ssometimes is more complicated

Kapcsolódó programok

Owncloud

  • személyes felhő, megy rpi-n is

Amazon EC2

  • számítási kapacitást visz át, elosztott rendszerekbe, ahol bucketeekben dolgoznak a felhasználók

FrostWire

  • Cloud downloader, Bit Torrent client, media player, preview and play while download
  • connect to different torrent search engine

Bit Torrent

  • megkeresi a bit torent index fájlt a fájlszerveren (Pirate Bay)
  • tovább meg a trackerhez a .torentfájlban talált pointer alapján
  • a tracker megmondja, hogy kinek lehet meg az adott rész, nem pontosan, csak lehetőségként, úgy, hogy az aki keresi annak meglegyen az ami a másiknál hiányzik
  • magnet linkek egy P2P rendszerre mutató pointerek

VirtualBox

  • VM teszteléshez

planetlab

  • egy elosztott szerverkutatóhálózatok között

Irodalom


Gyakorlati összefoglaló

Kliens-szerver kapcsolat

kitlei.web.elte.hu/segedanyagok

orsi-gyak1

mintafájlok: gy1/ElsoSzerver.java | gy1/ElsoKliens.java | gy1/Szerver2.java

Szerver:

  • Első lépésben elindítjuk egy PORT-on a ServerSocket segítségével: ServerSocket ss = new ServerSocket(PORT);
  • Várunk a kliens megjelenésére: Socket s = ss.accept(); FIGYELEM! Ez akár évekig is hajlandó várni, amíg a kliens meg nem jelenik, vagy a programot ki nem kapcsoljuk!
  • A szerverre bejövő információkat Scanner segítségével kapjuk el: Scanner sc = new Scanner(s.getInputStream());
  • A szerveren kimenőket meg PrintWriterel küldjük ki: PrintWriter pw = new PrintWriter(s.getOutputStream());

teljes kód:

import java.io.*;
import java.util.*;
import java.net.*;

public class ElsoSzerver {
	public static void main(String[] args) throws Exception {
		int PORT = 12345;
		try (
			ServerSocket ss = new ServerSocket(PORT);
			Socket s = ss.accept();
			Scanner sc = new Scanner(s.getInputStream());
			PrintWriter pw = new PrintWriter(s.getOutputStream());
		) {
			String name = sc.nextLine();

			pw.println("Hello, " + name);
			pw.flush();
		}
	}
}

Kliens:

Kliensként ilyenkor felcsatlakozhatunk PuTTY-al is akár: Hostname: localhost; Port: 12345; Connection type: Raw; Close window on exit: Never beállításokkal.

De írhatunk sajátot is:

  • Először adjuk meg hova szeretnénk kapcsolódni: String MACHINE = "localhost"; itt a "localhost"ot akár lecserélhetjük egy IPra is: "127.0.0.1"
  • Adjuk meg a PORTot: int PORT = 12345;
  • Kapcsolódjunk: Socket s = new Socket(MACHINE, PORT);
  • A kliensre bejövő adatfolyamra várjunk egy Scanner segíségével: Scanner sc = new Scanner(s.getInputStream());
  • A kliensnél kiemenő adatokat a szokásos PrintWriter segítségével oldhatjuk meg: PrintWriter pw = new PrintWriter(s.getOutputStream()); De vigyázzunk a használatával, ugyanis, minden kiíratás után flushölni kell amit írtunk. Ez küldi el a szervernek, ha egymás után több dolgot kiíratunk a PrintWriterre és utánna flushölünk akkor egybe fog lemenni az egész, nem soronként! Azaz így: pw.println("AzEnNevem"); pw.flush();

teljes kód:

import java.io.*;
import java.util.*;
import java.net.*;

public class ElsoKliens {
	public static void main(String[] args) throws Exception {
		String MACHINE = "localhost";
		int PORT = 12345;
		try (
			Socket s = new Socket(MACHINE, PORT);
			Scanner sc = new Scanner(s.getInputStream());
			PrintWriter pw = new PrintWriter(s.getOutputStream());
		) {
			pw.println("AzEnNevem");
			pw.flush();

			String valasz = sc.nextLine();

			System.out.println(valasz);
		}
	}
}

Scannernél hasznosak lehetnek:

sc.hasNextLine() - várja következő sort vagy a halott servert

sc.hasNext() - átugorja az összes whitespacet

sc.hasNextInt() - átugorja a whitespaceket és számot vár válaszként


Feladat: kliens küld -> szerver feldolgoz -> kliens visszakapja a feldolgozott formát

eredeti: gyak2

fájlok: gy2/Szerver3.java - mintafájl-0ra lép ki | gy2/server.java - saját megoldás-karakteres üzenetre lép ki

A kliens küldjön át sorban egész számokat a szervernek. A számokat a kliens egy fájlból olvassa be. A szerver mindegyik számra meghív egy függvényt, ami egész számot készít (mondjuk n ↦ 2*n+1), majd az eredményt visszaküldi a kliensnek. A kliens a visszakapott eredményeket egy fájlba írja ki sorban. Ha a 0 szám következne a kliensoldalon, akkor a kliens kilép.

  • A kliens most küldje át az összes adatot a szervernek, és csak utána fogadja a visszaérkező számokat; hasonlóan, a szerver fogadja az összes számot, és csak utána küldje el őket átalakítva a kliensnek.

  • A szerver várakozzon a kliens kilépése után új kliensre, és ez ismétlődjön a végtelenségig.

Az érdekes rész a sorban egymás után végtelen sok klienst kiszolgáló szerver:

while (true){
	try (
		ServerSocket ss = new ServerSocket(PORT);
		Socket s = ss.accept();
		Scanner sc = new Scanner(s.getInputStream());
		PrintWriter pw = new PrintWriter(s.getOutputStream());
		) {
		while(sc.hasNextInt()){
			Integer nr = sc.nextInt(); 	//beérkezik az adat
			tmp.add(toInt(nr));		//feldolgozás
		}	
		answer(tmp, pw);	//válasz
	}
}

Feladat: FTP server

eredeti: gyak3

fájl: gy3/Szerver4.java

A kliens átküld egy fájlnevet a szervernek. A szerver küldje vissza a fájl tartalmát soronként, ha a fájl létezik, különben pedig egy szöveges hibaüzenetet. Lényeges rész:

static void simpleFtp(Scanner sc, PrintWriter pw) {
	String filename = sc.nextLine();

	try (Scanner scFile = new Scanner(new File(filename))) {
		while (scFile.hasNextLine()) {
			String line = scFile.nextLine();
			pw.println(line);
		}
	} catch (IOException e) {
		pw.println("Error: " + e);
	} finally {
		pw.flush();
	}
}

Feladat: egyszerre több kliens ugyanazon a porton vagy másikon!

eredeti: gyak4

fájl: gy4/Szerver8.java Felmerülhet, hogy mi van agyszerre több klienst szeretnénk kezelni egy szerveren egy PORTon. Megoldásként duplikálhatunk mindent, azaz:

  • Létrehozzuk a PORTot: int PORT = 12345; és hallgatózunk rajta: ServerSocket ss = new ServerSocket(PORT);
  • Figyelünk egy Scanner ésegy Printwriterrel, mint eddig:
     Socket s1 = ss.accept();
     Scanner sc1 = new Scanner(s1.getInputStream());
     PrintWriter pw1 = new PrintWriter(s1.getOutputStream());
  • Ezt duplikáljuk:
     Socket s2 = ss.accept();
     Scanner sc2 = new Scanner(s2.getInputStream());
     PrintWriter pw2 = new PrintWriter(s2.getOutputStream());
  • Ezután viszont szabadon kezelhetjük a kettőt, külön, vagy akár egymásnak is átirányíhatjuk
     String name1 = sc1.nextLine();
     String name2 = sc2.nextLine();

Ugyanakkor kezelhetjük őket több porton is:

  • ehhez csak azt kell megváltoztatni, hogy a második ServerSocket egy másik porton hallgatózzon:
     ServerSocket ss2 = new ServerSocket(54321);
     Socket s2 = ss2.accept();
     Scanner sc2 = new Scanner(s2.getInputStream());
     PrintWriter pw2 = new PrintWriter(s2.getOutputStream());

Teljes kód:

public static void main(String[] args) throws Exception {
	int PORT = 12345;

	try (
		ServerSocket ss = new ServerSocket(PORT);
		//ServerSocket ss2 = new ServerSocket(54321);

		Socket s1 = ss.accept();
		Scanner sc1 = new Scanner(s1.getInputStream());
		PrintWriter pw1 = new PrintWriter(s1.getOutputStream());

		//Socket s2 = ss2.accept();
		Socket s2 = ss.accept(); //ezt kommentelni kell ha két porton szeretnénk!
		Scanner sc2 = new Scanner(s2.getInputStream());
		PrintWriter pw2 = new PrintWriter(s2.getOutputStream());
		) {
		String name1 = sc1.nextLine();
		String name2 = sc2.nextLine();

		while (true) {
			if (!sc1.hasNextLine())   break;
			sendMsg(name1, sc1, pw2);

			if (!sc2.hasNextLine())   break;
			sendMsg(name2, sc2, pw1);
		}
	}
}

Ezt oldja meg az alábbi feladat is:

A szerverhez kapcsolódjon két kliens egymás után (ugyanazon a porton) úgy, hogy a szerver mindkét kapcsolatot egyszerre tartja nyitva. A kliensek először egy-egy sorban a saját nevüket küldik át, majd felváltva írhatnak be egy-egy sornyi szöveget. A beírt üzeneteket küldje át a szerver a másik kliensnek ilyen alakban: <másik kliens neve>: <másik kliens üzenete>. Ha valamelyik kliens bontja a kapcsolatot, akkor a szerver zárja be a másik klienssel a kapcsolatot, és lépjen ki.

Párhuzamosság

kitlei.web.elte.hu/segedanyagok

orsi-gyak5

mintafájlok: gy5/Parhuzamossag.java

Server - szálak

  • létrehozunk szálat: Thread t1 = new Thread()
  • elindítjuk: t1.start();
  • megvárhatjuk, hogy befejezze a futását: t1.join(); egyben:
Thread t1 = new Thread(() -> {
	myClass.myFun1();
	myClass.myFun2();
});
Thread t2 = new Thread(() -> {
	myClass.myFun1();
	myClass.myFun2();
});

t1.start();		// versenyhelyzet (race condition)
t2.start();
t1.join();
t2.join();
  • ebben az esetben 3 szálunk volt: t1, t2, main. Ha nem írjuk ki a t1.join();t akkor a main nem várja be annak a futánsak a végét és tovább lép. Adott esetben, ha mindez egy try(){} blokkban történik akkor a join() elhagyásával az erőforrásokat is elengedhetjük, és így például a t1 szál is megszakad! Jó plda erre a gy7/MultiThreadChatServer.java amiben ha elhagynánk a join()okat akkor pont ez történne!
  • ha valamit szeretnénk elérni mindkét szálról, úgy hogy annak az értéke bizotsan ne módosuljon amíg az egyik szál használja a másik szál által akkor szinkronizálnunk kell: synchronized (szinkroizálandó){}

egyben:

int[] counter = { 0 };

Thread t1 = new Thread(() -> {
	for (int i = 0; i < 100000; ++i) {
		synchronized (counter) {
			++counter[0];
		}
	}
});

Kliens - szálak

Természetesen mindezt a kliensnél is megtehetjük, ha pl az egyik szálon írunk, másikon olvasunk.

példa: kecskés feladat : gy6/MyGoats.java


Feladat: párhuzamosított chatserver

Készíts olyan chat alkalmazást, amelyben a két kliensnek nem kell egymásra várnia soronként, hanem bármikor beszélhetnek egymáshoz, és ez azonnal kiíródik a másik kliensnél.

részlet:

try (
	ServerSocket ss = new ServerSocket(12345);
	) {
	while (true) {
		ClientData client = new ClientData(ss);
		synchronized (otherClients) {
			otherClients.add(client);
		}

		new Thread(() -> {
			while (client.sc.hasNextLine()) {
				String line = client.sc.nextLine();

				synchronized (otherClients) {
					for (ClientData other : otherClients) {
						other.pw.println(line);
						other.pw.flush();
					}
				}
			}

			synchronized (otherClients) {
				otherClients.remove(client);
				try {
					client.close();
				} catch (Exception e) {
							// won't happen
				}
			}
		}).start();
	}
}

egész kód: gy7/MultiThreadChatServerV3.java

Távoli metódushívás

kitlei.web.elte.hu/segedanyagok

orsi-gyak8

Server - Deploy

mintafájl: gy8/RMIDeploy.java

Szeretnénk eléréni, hogy a kliens közvetlenül a serveren tudjon függvénykeet, metódusokat, eljárásokat hívni, paraméterezni. A Deployban létrehozzuk a serverünk pár plédányát:

  • Lefoglaljuk a PORTot, meg egyebet: Registry registry = LocateRegistry.createRegistry(PORT);
  • Létrehozzuk ezen a szerverünk egy példányát: registry.rebind("rmiAppend", new RemoteAppendTxtServer());
public static void main(String args[])
        throws Exception
    {
        final int PORT = 12345;

        Registry registry = LocateRegistry.createRegistry(PORT);
        // Registry registry = LocateRegistry.getRegistry();
        registry.rebind("rmiAppend", new RemoteAppendTxtServer());
     }

Server - server rész

Ezután mintha egy osztály lenne felkonfiguráljuk, létrehozunk változókat, konstruktorokat: mintafájl: gy8/RemoteAppendTxtServer.java

public class RemoteAppendTxtServer
    extends java.rmi.server.UnicastRemoteObject
    implements RemoteAppendTxtInterface
{
    String appendTxt;

    public RemoteAppendTxtServer() throws RemoteException
    {
        this("default");
    }
    
    public String appendTxt(String str) throws RemoteException
    {
        return str + appendTxt;
    }
}  

Server - interface

Ezután már csak egy interfacere van szükségünk, hogy tudjunk kapcsolódni a klienstől: mintafájl: gy8/RemoteAppendTxtInterface.java

import java.rmi.*;

public interface RemoteAppendTxtInterface extends Remote
{
    String appendTxt(String str) throws RemoteException;
    // MyData appendTxt(MyData str) throws RemoteException;
} 

Kliens

A kliensnél létrehozzuk az interfacenek megfelelő proxynkat:

RemoteAppendTxtInterface rmiServer = (RemoteAppendTxtInterface)(registry.lookup(srvName));

Ahol mostantól nyugodtan hívhatjuk az interfacen megengedett eljárásokat:

String reply = rmiServer.appendTxt(text);

példa feladat:

Lottós feladat : Lottós feladat fájljai

Adatbázis kezelés

kitlei.web.elte.hu/segedanyagok

gy10 A táblákon csak a szokásos SQL parancsok használhatóak!


Osztott ZH 2019.05.20.

Elégségesért az alapfeladatot kell teljesen megoldani.

  • Az adatok (osztály neve, port stb.) a megadott alakban szerepeljenek a programban.
  • A megoldáshoz célszerű osztályokat, segédfüggvényeket, adatszerkezeteket stb. létrehozni.
  • Használhatók az alábbi segédanyagok:
    • A JDK dokumentációja itt érhető el.
    • A gyakorlatok anyagai (és az adatbáziskezeléshez szükséges jar fájlok) itt érhetők el.
  • A megoldást teljesen önállóan kell elkészíteni. Együttműködés/másolás esetén minden érintett fél elégtelent kap. A további feladatok eggyel növelik a megszerzett jegyet, és tetszőleges sorrendben adhatók hozzá a programhoz. Beadás: az elkészült megoldás fájljait zip-pel kell tömöríteni a feltöltéshez. IDE-ben készült megoldásnál a teljes projekt becsomagolható.

Alapfeladat

Kidolgozva: Server | kliens

!! Az alapfeladatban se a szervernek, se a kliensnek nem kell párhuzamosan (több szálon) működnie. Készíts olyan szervert az Auction osztályba, amely a 2121 porton indul el, és egy aukciós házat szimulál. A szerver egy klienst vár, majd a kliens lecsatlakozása után csatlakozhat újabb, és újabb kliens. A kliensek szövegesen kommunikálnak a szerverrel; az első sorban elküldik a nevüket, majd a következő sorokban az alábbi három lehetőségből választhatnak.

  • put <item_name>: az adott nevű tárgyat meghirdeti (tegyük fel, hogy még nincs azonos nevű tárgy), kezdetben 0 áron
  • list: lekérdezi a meghirdetett tárgyakat. A szerver először elküld egy számot (hány meghirdetett tárgy van), majd soronként egyet-egyet a név ár nyertes formában
  • bid <item_name>: a felhasználó licitál a tárgyra, eggyel megnövelve az értékét, és az aktuális nyertest a felhasználóra állítva Ehhez a szerverhez készíts egy klienst is az AuctionClient programba.

+1

Kidolgozva: Server2 | Kliens

Módositsd a szervert, hogy egyszerre tetszőlegesen sok klienst engedjen csatlakozni, és mind párhuzamosan használhassák az előző feladatban megvalósított parancsokat. Az aukciók legyenek limitált idejűek: a meghirdetéstől számítva 30 másodpercig tartanak. Az idő lejárta után befejeződnek: többet nem lehet rájuk licitálni, és nem jelennek meg a listában. Amikor az aukció lejár, a szerver üzenetet küld a győztes kliensnek a nyereményéről.

+1

A szerver exportáljon egy RMI objektumot, amely a BidHistory interfészen keresztül, a bid_history néven érhető el. Az interfésznek legyen egy olyan metódusa, ami visszaadja az összes eddigi licit adatait (ki, mire, mennyiért) egy időben növekvő listában. Az interfész másik metódusát meghívva lehessen átváltani nyitva/zárvatartás között. Amíg az aukciós ház zárva tart, a licitálás szünetel, és a szerver egy ezt jelző üzenetet küld vissza a klienseknek.

+1

A szerver tárolja el adatbázisban, ki hány tárgyat hirdetett meg eddig összesen. Ez az érték maradjon meg a szerver újraindításakor is, ne kezdődjön előről nulláról. Mindenki maximum három tárgyat hirdethet meg - az afölötti kéréseket a szerver figyelmen kívül hagyja.

Osztott ZH - régebbi

Alapfeladat

Kidolgozva: Server | Kliens

Készíts cikkek írására egy szerver-kliens alkalmazást. Készíts egy ujsag.Cikk típust, ami egy cikket tartalmaz, egy címet. valamint szavak listáját. Készíts egy ujsag.Server típust. Ami egy futtatható' Java osztály. A main függvény indítson egy szervert, az első paranccsori paraméterként megadott porton. es várja egymás utáni kliensek csatlakozásat. A klienstöl csatlakozás után először egy sort várjon. ami a cikk címét tartalmazza. majd ezután szavak sorozatát A szerver nem küld válaszokat a kliensnek A szerver tárolja el a kapott cikkeket egy adatszerkezetbe. Amennyiben egy cikk korábban már létezett. azt írja felül. Keszits egy ujsag.iro nevü futtatható Java osztályt. A program kérjen be a felhasználótól a standard bemeneten egy címet. majd szavak listáját a standard bemenet zárásáig. és azokat folyamatosan küldje el a paranccsori paraméterként megkapott szerveren. (az első parancssori paraméter a host. a második a port)

Osztott ZH - régebbi2

Alapfeladat

Kidolgozva: Server

Készíts sportmérkőzések lebonyolítására egy szerver-kliens alkalmazást.

  • Készíts egy sport.Pont típust, ami azt reprezentálja, ha egy csapat pontot szerzett. Tartalmazzon két adattagot: hányadik csapat (1, vagy 2) szerezte a pontot. és a játék hányadik másodpercében.
  • Készíts egy sport.Merkozes típust, ami egy mérkőzést reprezentál: tartalmaz két csapatnevet (stringek), valamint a pontok listáját.
  • Készíts egy sport.Szerver típust, ami egy futtatható Java osztály. A main függvény indítson egy szervert az első paranccsori paraméterként megadott porton, es várja egymás utáni kliensek csatlakozásat. A klienstől csatlakozás után először két sort várjon. ami a két csapat nevét tartalmazza, majd ezután pontok sorozatát. A kliens a pontoknál csak azt küldi el. melyik csapat szerezte a pontot (szám formájában), az idő automatikusan számolódik az alapján, a kliens hány rnásodperce csatlakozott. A szerver nem küld válaszokat a kliensnek. A szerver jelenítse meg a standard kimeneten az aktuális mérkőzés információit minden változás után.
  • Készíts egy sport.Feljegyzo nevű futtatható Java osztályt. A program kérjen be a felhasználótól a standard bemeneten két csapatnevet, majd sorok listáját a jatek_vege. üzenetig. A sorok vagy 1-est. vagy 2-est, vagy a latek_vege“ üzenetet tartalmazhatják.

About

osztott rendszerek | server - kliens | FTP | párhuzamosság | RMI | Adatbázis

http://kitlei.web.elte.hu/segedanyagok/felev/2018-2019-tavasz/osztott/

License:Mozilla Public License 2.0


Languages

Language:Java 100.0%