Kategória: Java standard könyvtárak.
A standard Java a java.net csomagban definiálja a hálózati kapcsolat felépítéséhez szükséges osztályokat, interfészeket, tehát nem kell használnunk külön könyvtárakat. Az alábbi példákat a https://cs.lmu.edu/~ray/notes/javanetexamples/ oldal alapján készítettem.
Olvasás az internetről
A Java haladó témák között szerepel egy internetről történő beolvasás példa. A hálózati kapcsolat lényege a Socket osztályban van megvalósítva. Egyetlen sort a következőképpen tudunk beolvasni, alkalmazva a Java 7 által nyújtott kivételkezelési egyszerűsítéseket:
import java.io.IOException; import java.net.Socket; import java.util.Scanner; public class ClientExample { public static void main(String[] args) { try (Socket socket = new Socket("djxmmx.net", 17)) { try (Scanner in = new Scanner(socket.getInputStream())) { System.out.println("Server response: " + in.nextLine()); } } catch (IOException e) { e.printStackTrace(); } } }
A djxmmx.net oldal a 17-es porton véletlenszerű idézeteket küld, a példában ezt olvassuk ki.
Dátum szerver és kliens
Lássuk ennek párját, egy egyszerű szervert:
import java.io.IOException; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Date; public class DateServer { public static void main(String[] args) { int port = 50000; try (ServerSocket listener = new ServerSocket(port)) { System.out.println("The date server is listening on port " + port); while (true) { try (Socket socket = listener.accept()) { System.out.println("A client has connected."); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); out.println(new Date().toString()); out.close(); System.out.println("Connection ended."); } } } catch (IOException e) { e.printStackTrace(); } } }
Ha elindítjuk, akkor többféle módon kipróbálhatjuk, pl. a putty nevű program segítségével (host: localhost, port: 50000, connection type: raw, close window on exit: never), vagy a curl segítéségével (curl localhost:50000). De írhatunk hozzá klienst is:
import java.io.IOException; import java.net.Socket; import java.util.Scanner; public class DateClient { public static void main(String[] args) { try (Socket socket = new Socket("localhost", 50000)) { try (Scanner in = new Scanner(socket.getInputStream())) { System.out.println(in.nextLine()); } } catch (IOException e) { e.printStackTrace(); } } }
Kétirányú kommunikáció: nagybetűsítés
A fent megadott módon valójában a szerver is küldhet információt a kliensnek és a kliens is a szervernek. Először lássunk egy szerver példát, amely tetszőleges szöveget vár inputként, és a nagybetűsített változatát küldi vissza:
import java.io.IOException; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; public class CapitalizeServer { public static void main(String[] args) { int port = 60000; try (ServerSocket serverSocket = new ServerSocket(port)) { System.out.println("The capitalization server is running on port " + port); while (true) { try (Socket socket = serverSocket.accept()) { System.out.println("A client has connected: " + socket); try (Scanner socketScanner = new Scanner(socket.getInputStream())) { PrintWriter output = new PrintWriter(socket.getOutputStream(), true); while (socketScanner.hasNextLine()) { output.println(socketScanner.nextLine().toUpperCase()); } output.close(); } System.out.println("Connection closed: " + socket); } } } catch (IOException e) { e.printStackTrace(); } } }
Próbáljuk ki putty segítségével: csatakozzunk a fent megadott módon, majd írjunk be tetszőleges szöveget.
A klienst is elkészíthetjük hozzá:
package nettest; import java.io.IOException; import java.io.PrintWriter; import java.net.Socket; import java.util.Scanner; public class CapitalizeClient { public static void main(String[] args) { try (Socket socket = new Socket("localhost", 60000)) { System.out.println("Enter lines of text then Ctrl+D or Ctrl+C to quit"); try (Scanner consoleRead = new Scanner(System.in)) { try (Scanner networkRead = new Scanner(socket.getInputStream())) { var out = new PrintWriter(socket.getOutputStream(), true); while (consoleRead.hasNextLine()) { out.println(consoleRead.nextLine()); System.out.println(networkRead.nextLine()); } } } } catch (IOException e) { e.printStackTrace(); } } }
Többszálú kliens kiszolgálás
A fenti példában vegyünk észre valamit: egyszerre csak egy klienst tud kiszolgálni a szerver! Próbáljunk meg pl. a putty segítségével kétszer csatlakozni: az első fog sikerülni, a második pedig várakozni fog (be ugyan tudunk írni szöveget de választ nem kapunk). Ám ha kilépünk az elsőből, akkor a második is végrehajtódik. Fejlesszük tovább: a már bemutatott egyik többszálú megoldással a csatlakozáskor induljon egy új szál, és azonnal flytassa a következő kliens kiszolgálását!
import java.io.IOException; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; import java.util.concurrent.Executors; class Capitalizer implements Runnable { private Socket socket; public Capitalizer(Socket socket) { this.socket = socket; } @Override public void run() { System.out.println("Connected: " + socket); try (Scanner in = new Scanner(socket.getInputStream())) { PrintWriter out = new PrintWriter(socket.getOutputStream(), true); while (in.hasNextLine()) { out.println(in.nextLine().toUpperCase()); } out.close(); } catch (IOException e) { e.printStackTrace(); } System.out.println("Disconnected: " + socket); } } public class CapitalizeServer { public static void main(String[] args) throws Exception { int port = 60000; try (var listener = new ServerSocket(port)) { System.out.println("The capitalization server is running on port " + port); var pool = Executors.newFixedThreadPool(3); while (true) { pool.execute(new Capitalizer(listener.accept())); } } } }
A példában egyszerre 3 kliens tud kiszolgálni. Ez a valóságban lehet jóval nagyobb; a könnyebb tesztelhetőség érdekében vettük le háromra. Indítsunk párhuzamosan 3 putty terminált a megadott módon, és mindegyik konzolra írjunk szöveget. Ha mindent jól csináltunk, megkapjuk válaszul a nagybetűsített változatát a beírt szövegnek. Most indítsunk egy negyediket: a kliens elindul, a szöveget be tudjuk írni, de választ nem kapunk. Ha viszont az első 3háromból egyet bezárunk, a nagyedik automatikusan szóhoz jut.