Hálózati kommunikáció
A programhoz szükséges hálózati kommunikációt szerencsére a Jáva net könyvtára segítségével könnyû megoldani. A részletek mellôzésével: a könyvtár definiál egy Socket osztályt, amely egyszerû TCP kapcsolat kiépítésére és azon adatok átvitelére szolgál.
Elôször létrehozunk egy új Socket-et, egyben megnyitva az összeköttetést a paraméterként megkapott gép 7777-es kapujával (port).
A TCP/IP hálózati rendszerben nem a programokat, hanem a kommunikációra szolgáló kapcsolódási pontokat, az ún. kapukat (port) azonosítjuk. Az elsõ 7777 kapu cím használatát általában korlátozzák, csak rendszergazda jogosultságú programok olvashatják, a többi a "mezei" felhasználók rendelkezésére áll. A kapuk egy része, az ún. jól ismert kapuk (well-known ports) minden számítógépen szabványos funkciókat betöltõ programokhoz tartoznak.
Egy tipikus szerver mûködésének lépései:
- Az egyes kapukhoz tartozó kommunikációs csatornákat socket-eknek nevezzük. Kapcsolatorientált kommunikációnál kétfajta socket használatos: a szerver oldalon egy kiépülésre váró kapcsolatot az ún. ServerSocket osztály egy példánya valósítja meg:
ServerSocket server = new ServerSocket(port); - A kliens/szerver rendszerekben a szerver passzív szerepet játszik, arra várakozik, hogy egy kliens megszólítsa. Ha sikeresen kiépül a kapcsolat, a szerver visszatér az accept hívásból a kiépült kapcsolatot reprezentáló Socket példányból.
Socket socket = server.accept(); - A socket-bõl két, az input - kliensbõl szerver felé irányuló - és az output - szerverbõl kliens felé tartó - adatfolyam kapható meg.
InputStream input = socket.getInputStream();
OutputStream input = socket.getOutputStream(); - A szerver törzse az így megszerzett input adatfolyamot olvassa, a vett információt értelmezi és esetleg az output folyamon válaszol.
- Az adatcsere végén a szervernek vagy a kliensnek le kell zárnia a kapcsolatot jelentõ socket-et. Ehhez elõször illik az adatfolyamokat lezárni.
input.close();
output.close();
socket.close();
Eztán minden indulhat elölrõl, pontosabban a 2. lépéstõl, ahol a szerver új kérésre vár. Amennyiben a szerverünket szeretnénk egyidejûleg több kérés kiszolgálására is felkészíteni, akkor a 3-5 lépéseket egy-egy külön szállal (Thread) érdemes végrehajtatni, miközben az eredeti szál a 2-es lépésben várakozik.
A kliens oldali program még ennél is egyszerûbb. Elõször felvesszük a kapcsolatot az adott Internet címmel (vagy névvel) rendelkezõ számítógép megfelelõ kapuján várakozó kiszolgáló programmal:
Innen a lépések megegyeznek a szerver oldal 3-5-ös lépéseivel.
Szerver oldal:
package javaclientservercodeblogger; import java.net.*; import java.io.*; import java.util.*; public class Server extends Thread { /*Szerver port, kliensek listája <ArrayList>*/ private final int port = 7777; private ServerSocket ss; private ArrayList<clientThread> clients = new ArrayList(); public Server() { try { /* A szerver indítása a megadott porton. */ System.out.println("\nA szerver indulásra kész a következő porton: " + port); ss = new ServerSocket(port); System.out.println("\nSzerver sikeresen elindúlt"); } catch (IOException e) { System.out.println(e); } } public void run() { try { while (true) { /* Kliensekre várakozunk, melyek csatlakozni szeretnének */ System.out.println("\nKliensre várakozunk..."); addClient(); /* Elfogadjuk a csatlakozni próbálkozó klienseket. */ } } catch (IOException e) { System.out.println(e); } } public synchronized void handle(int ID, String input) throws IOException{ /* A kliens üzeneteket olvassuk */ System.out.println("\nÜzenet a klienstől: "+input); /* Ha a kliens üzenet a HELLO SERVER, akkor a szerver a kliensnek HELLO CLIENT -el válaszol. */ if(input.equals("HELLO SERVER")) { clients.get(findClient(ID)).send("HELLO CLIENT!"); } } public void addClient() throws IOException { clientThread client = new clientThread(this, ss.accept()); client.open(); /*Megnyítjuk a kliens IO stream-eket. */ client.start(); clients.add(client); /* Hozzáadjuk a klienset a kliens listához <ArrayList>*/ System.out.println("\nKliens elfogadva."); client.send(">> ÜDV, KLIENS! "); } /* Removing the client */ public void removeClient(int ID) { clients.remove(findClient(ID)); System.out.println("\nA kliens eltávolítva."); } /* Finding client position in the clients list*/ public int findClient(int ID) { for (int i = 0; i < clients.size(); i+) { if (clients.get(i).ID == ID) { return i; } } return -1; } public static void main(String[] args) { new Server().start(); new Client("localhost", 7777).start(); } }
Szerver oldal kliens kapcsolatai:
package javaclientservercodeblogger; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; class clientThread extends Thread { private Socket s; private DataOutputStream out; private DataInputStream in; public int ID = -1; private Server srv; public clientThread(Server srv, Socket s) { this.srv = srv; this.s = s; /* Beállítjuk a kliens ID -t*, a portbol kapjuk. / ID = s.getPort(); } public void run() { try { while (true) { /* A szerver oldali üzenetek olvasása. */ srv.handle(ID, (String) in.readUTF()); } } catch (IOException e) { /* Ha valami olvasási probléma van, eltávolítjuk a klienset. */ srv.removeClient(ID); } } public void send(String msg) throws IOException { /* Üzenet küldése a szervernek */ out.writeUTF(msg); } public void open() throws IOException { /* IO stream-ek megnyítása, miután a socket kapcsolódva van. */ out = new DataOutputStream(s.getOutputStream()); in = new DataInputStream(s.getInputStream()); } public void close() throws IOException { /* Socket bezárása (kapcsolat) és stream-ek bezárása. */ in.close(); out.close(); s.close(); } }
Kliens oldal:
package javaclientservercodeblogger; import java.io.*; import java.net.*; public class Client extends Thread { private Socket s; private DataInputStream in; private DataOutputStream out; public Client(final String host, final int port) { /* Probálkozunk kapcsolatot létesíteni a szerverrel */ try { System.out.println("Kapcsolódás a szerverhez: " + host + " és port: " + port); s = new Socket(host, port); if(s.isConnected) { /* Ha sikerült kapcsolódni, akkor megnyítjuk a stream-eket és egy üdvözlő üzenetet küldünk a szervernek. */ open(); System.out.println("Kapcsolódva a szerverhez: " + host + " és port: " + port); send("HELLO SERVER"); } } catch (IOException e) { /* Sikertelen kapcsolódás esetén hiabüzenet.. */ System.out.println("Nem sikerült csatlakozni a szerverhez. " + e.getMessage()); } } public void run() { try { while (true) { /* A szervertől kapott üzenetek olvasása. */ String message = in.readUTF(); System.out.println("Üzenet a szervertől: "+message); } } catch (IOException e) { /* Olvasási problémák, kapcsolat megszakítása. */ close(); System.out.println("Kapcsolat megszakítva. " + e.getMessage()); } } public void open() throws IOException { /* IO stream-ek megnyítása, miután a kapcsolat létrejött.*/ in = new DataInputStream(s.getInputStream()); out = new DataOutputStream(s.getOutputStream()); } public void close() { /* Lezárjuk a kliens stream-eket. */ try { out.close(); in.close(); s.close(); } catch (IOException e) { System.out.println(e.getMessage()); } } /* Ünzenet küldése a szervernek. */ public void send(String msg) throws IOException { out.writeUTF(msg); } } Köszi, hogy elolvastad a bejegyzésemet remélem megtaláltad amit kerestél :) és le is töltheted a forráskódot innen.