Uniwersytet Łódzki
Wydział Matematyki i Informatyki, Katedra Analizy Nieliniowej
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
Warstwa aplikacji
Warstwa Transportowa
Warstwa Sieci
Warstwa Łącza
TCP, UDP
IP, ICMP, IGMP HTTP, FTP
ARP, RARP Model odniesienia TCP/IP
Porty
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)
TCP lub UDP
port port port port port
app app
app app
app
port payload
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.
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
Aplikacja wyświetlająca zawartość strony na standardowe wyjście.
Przykład 2.
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
Aplikacja wyświetlająca zawartość strony na standardowe wyjście. Otwieranie połączenia dla określonego protokołu.
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.
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
Aplikacja pozwalająca na zapis do strumienia wyjściowego.
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
Baza danych
Serwer
„Gruby” klient
Logika usługowa
Architektura Klient-Serwer
Porty
Serwer Klient
Porty
Nasłuchiwanie
Porty
Serwer Klient
Porty
Przydzielenie portu
•nazwa hosta serwera
•numer portu serwera, na którym nasłuchuje
Przywiązanie klienta do konkretnego portu Port, na którym klient nasłuchuje
Przepięcie klienta na nowy port, w celu zwolnienia portu do nasłuchiwania
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.
ServerSocekt Socekt
Architektura wielowarstwowa
Cienki klient
Logika usługowa Logika usługowa
Logika usługowa
Baza danych Warstwa pośrednicząca
Warstwa pośrednicząca
Zalety architektury rozproszonej:
•Skalowalność aplikacji
•Dostępność
•Rozszerzalność aplikacji
•Bezpieczeństwo
Usługi
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
Przykład architektury wielowarstwowej
Czytanie i zapis z gniazda
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
Klient Serwer
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
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