Podstawy Programowania sieciowego w Javie Wykład 10 mgr inż. Michał Misiak
Podstawy sieci W Javie aplikacje sieciowe mogą być tworzone w warstwie aplikacji bez koniczności obsługi UDP/TCP Obsługa sieci jest niezależna od platformy Typ transportu: UDP: brak gwarancji doręczenia pakietu, brak gwarancji sekwencyjności doręczania pakietów, multicast TCP: niezawodna komunikacja, charakter połączeniowy, kontrola przepływu i transmisji Model odniesienia TCP/IP Warstwa aplikacji HTTP, FTP Warstwa Transportowa TCP, UDP Warstwa Sieci IP, ICMP, IGMP Warstwa Łącza ARP, RARP
Porty Przeznaczenie danych w Internecie określane jest przez: app app app app Przeznaczenie danych w Internecie określane jest przez: adres IP (32 bity) numer portu (16 bitów) Porty wykorzystywane są do kojarzenia aplikacji z danymi przychodzącymi na interfejs Numery portów: 0 – 65535 Zastrzeżone numery portów: 0 – 1023. Wykorzystywane do usług takich jak HTTP, FTP, etc… W TCP serwer rejestruje się do nasłuchiwania na danym gnieździe, skojarzonym z określonym portem (bind) app port port port port port TCP lub UDP payload port
Uniform Resource Locator Pozwala na lokalizację zasobów (np. plików, baz danych, komend, etc…) w Internecie URL reprezentowany przez klasę URL w pakcie java.net URL składa się z dwóch elementów: Identyfikatora protokołu Nazwy zasobów Tworzenie URL: URL ul = new URL("http://www.ul.lodz.pl/"); Tworzenie URL z uwzględnieniem kodowania znaków specjalnych: URI uri = new URI("http", "foo.com", "/hello world/", ""); Metody do parsowania URL: getProtocol, getAuthority, getHost, getPort, getPath, getQuery, getFile, getRef Otwieranie strumienia na URL: metoda OpenStream, która zwraca java.io.InputStreamobject Połączenie z zasobami z wykorzystaniem określonego protokołu dla URL: metoda openConnection zwraca URLConnection, możliwość zrzutowania na konkretny protokół java.net.HttpURLConnection
Przykład 1. Aplikacja wyświetlająca zawartość strony na standardowe wyjście. import java.net.*; import java.io.*; public class URLReader { public static void main(String[] args) throws Exception { URL yahoo = new URL("http://www.yahoo.com/"); BufferedReader in = new BufferedReader( new InputStreamReader( yahoo.openStream())); String inputLine; while ((inputLine = in.readLine()) != null) System.out.println(inputLine); in.close(); } Źródło: http://java.sun.com/docs/books/tutorial/networking/urls/readingURL.html
Przykład 2. Aplikacja wyświetlająca zawartość strony na standardowe wyjście. Otwieranie połączenia dla określonego protokołu. import java.net.*; import java.io.*; public class URLConnectionReader { public static void main(String[] args) throws Exception { URL yahoo = new URL("http://www.yahoo.com/"); URLConnection yc = yahoo.openConnection(); BufferedReader in = new BufferedReader( new InputStreamReader( yc.getInputStream())); String inputLine; while ((inputLine = in.readLine()) != null) System.out.println(inputLine); in.close(); } Źródło: http://java.sun.com/docs/books/tutorial/networking/urls/readingURL.html
Pisanie pod wskazany URL Kroki wymagane do stworzenia klienta piszącego pod wskazany URL utworzenie URL pobranie obiektu URLConnection ustawienie właściwości pisania do strumienia otwarcie połączenia do zasobów pobranie strumienia wyjściowego z obiektu połączenie zapis do strumienia wyjściowego zamknięcie strumienia wyjściowego
Przykład 3. Aplikacja pozwalająca na zapis do strumienia wyjściowego. import java.io.*; import java.net.*; public class Reverse { public static void main(String[] args) throws Exception { ... (1) URL url = new URL(args[0]); (2) URLConnection connection = url.openConnection(); (3) connection.setDoOutput(true); (4) OutputStreamWriter out = new OutputStreamWriter( connection.getOutputStream()); (5) out.write("string=" + stringToReverse); out.close(); } Źródło: http://java.sun.com/docs/books/tutorial/networking/urls/readingURL.html
InetAddress Klasa reprezentuje 32 bitowy lub 128 bitowy adres IP na protokole transportowym UDP lub TCP Złożony jest z adresu IP oraz nazwy hosta Dwa typy adresów: multicast i unicast Metody: (static) getLocalHost() – zwraca obiekt klasy InetAddres opisujący lokalny komputer String getHostAddress() – zwraca adres w postaci XXX.XXX.XXX.XXX String getHostName() – zwraca adres w postaci maszyna.domena1.domena2 … Metody pomocnicze postaci: is???(), np. isMulticastAddress()
Architektura zcentralizowana
Architektura Klient-Serwer Architektura rozproszona Serwer „Gruby” klient Logika usługowa Skalowalność aplikacji Dostępność Rozszerzalność (extensibility) aplikacji Zdolność do używania obcych zasobów (resource load) Bezpieczeństwo Problemy modeli innych niż zcentralizowany: Dodatkowa złożoność aplikacji Wiele punktów, w których mogą wystąpić błędy Ograniczenia związane z przepustowością łączy komunikacyjnych Baza danych
Architektura Klient-Serwer Port, na którym klient nasłuchuje Przywiązanie klienta do konkretnego portu Serwer Klient nazwa hosta serwera numer portu serwera, na którym nasłuchuje Porty Porty ServerSocekt Socekt Nasłuchiwanie Przepięcie klienta na nowy port, w celu zwolnienia portu do nasłuchiwania Serwer Klient Porty Porty Przydzielenie portu Gniazdo (socket): jest punktem końcowym wykorzystywanym do zestawiania dwukierunkowego połączenia pomiędzy działającymi aplikacjami w sieci. Gniazdo jest przywiązane do wybranego portu, tak że warstwa TCP może identyfikować aplikację, do której powinny zostać dostarczone dane.
Architektura wielowarstwowa Zalety architektury rozproszonej: Skalowalność aplikacji Dostępność Rozszerzalność aplikacji Bezpieczeństwo Wady architektury rozproszonej: Dodatkowa złożoność aplikacji Potencjalnie wiele miejsc, w których mogą wystąpić błędy Ograniczenia związane z przepustowością łączy komunikacyjnych Warstwa pośrednicząca Warstwa pośrednicząca Cienki klient Logika usługowa Logika usługowa Logika usługowa Baza danych Usługi
Przykład architektury wielowarstwowej
Czytanie i zapis z gniazda Klient Serwer Utwórz gniazdo. Wymagana nazwa maszyny oraz numer portu. Pobierz strumień wejściowy i wyjściowy: PrintWriter i BufferedReader Czytaj linie po linii z BufferedReader i pisz do PrintWriter Zamknij strumienie Zamknij połączenie Utwórz gniazdo ServerSocekt na określonym porcie Zadeklaruj zamienną typu ClientSocket Użyj metody accept w celu odebrania i ustanowienia przychodzącego połączenia (utwórz wątek do obsługi odebranego połączenia) Pobierz strumień do pisania i czytania (PrintWriter i BufferedReader) Pisz i czytaj ze strumieni. Zamknij strumienie Zamknij połączenia Metoda accpet zwraca gniazdo, które ma przypisany zdalny port i adres IP.
Protokół Opisuje sposób komunikacji pomiędzy klientem i serwerem. Przeważnie realizowane jako automat W przypadku protokołu tekstowego można wykorzystać tokenizer Tokenizer: utworzyć tokenizer z początkowego ciągu znaków odbieranie kolejnych części ciągu znaków (tokenów) za pomocą nextToken liczba tokenów pozostałych do odebrania: countTokens
Przykład ‘Tokenzier’ public class TokenizerTest { public static void main(String[] args) { if (args.length == 1) { String input = args[0], delimiters = „;”; StringTokenizer token = new StringTokenizer(input, delimiters); while (token.hasMoreTokens()) { System.out.println(token.nextToken()); } }else { System.out.println("Podaj ciag znakow„);
Przykład Aplikacja Serwer: KnockKnockServer Aplikacja Klient: KnockKnockClient Protokół: KnockKnockProtocol
Transport UDP Datagram – jest to pojedyncza, niezależna wiadomość przesyłana w sieci, której czas dostarczenia, poprawność nie są gwarantowane Istnieje możliwość komunikacji multicast Java do obsługi Transportu UDP oferuje klasy: DatagramSocket, DatagramPacket, MulticastSocket - nie istnieje coś takiego jak kanał -
Aplikacja Klient-Server dla UDP Kroki przy pisaniu aplikacji klienta utworzenie gniazda typu DatagramSocket (nie wymagany port) utworzenie pakietu DatagramPacket pobranie adresu maszyny (InetAddress.getByName()) wysłanie pakietu metoda send Odebranie pakietu od serwera metoda receive Pobranie zawartości pakietu za pomocą metody getData Kroki przy pisaniu aplikacji serwera Utworzenie gniazda DatagramSocket Odebranie pakietu metodą receive Pobranie adresu i portu na który ma być wysłana wiadomość Przygotowanie DatagramPacekt do wysłania Wysłanie DatagramPacket metodą send Zamknięcie gniazda
Przykład QuoteServerThread QuoteServer QuoteClient
MultiCast Specjalny typ gniazda umożliwiający nasłuch na transmisję realizowaną przez serwer do wielu klientów tzw. broadcast Klient nie inicjuje transmisji, tylko nasłuchuje. Serwer wysyła pakiety w określonych interwałach DatagramPacket konstruowany jest z wykorzystaniem InetAddress oraz numeru portu. Klient do nasłuchiwania korzysta z MulticastSocket, dołączając się za pomocą metody join(grupa), do grupy odbiorców Grupa odbiorców jest to adres, na którym realizowana jest transmisja multicast