310 likes | 512 Views
Gniazdka w Javie . Daniel Piasta. Gniazdo - Definicja. Gniazdo (socket) – pojęcie reprezentujące dwukierunkowy punkt końcowy połączenia. Dwukierunkowość oznacza możliwość wysyłania i odbierania danych.
E N D
Gniazdka w Javie Daniel Piasta
Gniazdo - Definicja • Gniazdo (socket) – pojęciereprezentujące dwukierunkowy punkt końcowy połączenia. Dwukierunkowość oznacza możliwość wysyłania i odbierania danych. Wykorzystywane jest przez aplikacje do komunikowania się przez sieć w ramach komunikacji międzyprocesowej.
Pojęcie gniazda pojawiło się pierwszy raz w latach osiemdziesiątych w środowisku Unix jako Berkley Sockets Interface (ich odpowiednikiem w Windows jest WinSock). Jego zadaniem jest umożliwienie komunikacji pomiędzy dwoma oddalonymi od siebie komputerami. Z punktu widzenia aplikacji działającej w systemie operacyjnym gniazdo można traktować jako końcowy punkt komunikacji.
Unikalne gniazdo oznacza się adresem IP i numerem portu. Numery portów mogą przyjmować wartość od 1 do 65535 z tym, że niektóre z wartości są zarezerwowane dla typowych usług (patrz wykład o protokołach warstwy aplikacji). W związku z tym typowo przyjmuje się, że aplikacje użytkowników korzystają z portów o numerach powyżej 1024.
W systemach operacyjnych dostępne są trzy rodzaje gniazd. • Pierwsze z nich, gniazdo do przesyłania datagramów, wykorzystuje protokół bezpołączeniowy UDP a co za tym idzie nie gwarantuje dostarczenia danych. • Drugi typ to gniazda strumieniowe (ang. stream sockets). Używają one protokołu TCP na warstwie transportowej a co za tym idzie gwarantują zarówno dostarczenie wysłanego pakietu (w przypadku jego zagubienia następuje retransmisja) jak i kolejność zgodną z tą w jakiej zostały wysłane. • Trzeci typ to gniazda surowe (Nie występują w Javie) (ang. raw sockets). Umożliwiają one bezpośredni dostęp do protokołów niższej warstwy.
Klasa Socket reprezentuje gniazdo komunikacyjne dla protokołu TCP • Klasa ServerSocket reprezentuje gniazdo nasłuchu po stronie servera. • Klasa DatagramSocket reprezentuje gniazdo UDP (komunikacja pakietowa)
Adresowanie w Javie • Adres gniazdka składa się z adresu komputera (hosta) oraz portu komunikacji • Adres hosta może mieć format tekstowy, zgodny z używanym serwisem nazewniczym, lub w postaci adresu IP
Adresowanie w Javie • Klasa InetAdress • Reprezentuje adres IP • Metody: • getByAddress(byte[] addr) - Tworzy obiekt na podstawie adresu IP w postaci binarnej • getByAdress(String host, byte[] addr) - Tworzy obiekt na podstawie nazwy hosta i adresu IP • getByName(String host) - Tworzy obiekt na podstawie nazy hosta • getLocalHost - Obiekt reprezentujący adres lokalny hosta.
Klasy Inet4Adress i Inet6Adress dziedziczą po klasie InetAdress i reprezentują adresy IP w wersji 4 i 6
InetAdress - Przykład • InetAddress address = InetAddress.getByName("math.uni.lodz.pl"); • InetAddress address = InetAddress.getByName("78.46.84.171"); • InetAddress address = InetAddress.getLocalHost();
Klasa Socket • Klasa Socket udostępnia mechanizmy komunikacji strumieniowej peer - to - peer zarówno dla serwera jak i klienta. Odpowiada ona także za nawiązywanie połączenia z serwerem po stronie klienta.
Klasa Socket - Konstruktory • Utworzenie obiektu klasy Socket odbywa się przez użycie jednego z konstruktorów tej klasy: • Socket()— utworzenie gniazda • Socket(InetAddress address, int port)— utworzenie gniazda oraz próba nawiązania połączenia z serwerem • Socket(InetAddress address, int port,InetAddress localAddr, int localPort)— utworzenie gniazda z dowiązaniem lokalnym oraz próba nawiązania połączenia z serwerem • Socket(String host, int port)— utworzenie gniazda oraz próba nawiązania połączenia z serwerem na maszynie o podanej nazwie • Socket(String host, int port, InetAddress localAddr, int localPort)— utworzenie gniazda z dowiązaniem lokalnym oraz próba nawiązania połączenia z serwerem na maszynie o podanej nazwie
Klasa Socket - Metody • Klasa Socket udostępnia metody niezbędne do popranej komunikacji. Najważniejsze z nich to: • void bind(SocketAddress bindpoint) — przyporządkowanie do lokalnego adresu (nadanie nazwy) • void close() — zamknięcie gniazda • void connect(SocketAddress endpoint) — próba nawiązania połączenia z serwerem • void connect(SocketAddress endpoint, int timeout) — próba nawiązania połączenia z serwerem w określonym czasie • ObjectInputStream getIntStream() - zwraca strumień wejściowy dla danego gniazda • ObjectInputStream getOutputStream() - zwraca strumień wyjściowy dla danego gniazda
Klasa Socket - Przykład //Pobranie adresu sieciowego InetAddress addr =InetAddress.getByName("localhost"); //Otwarcie połączenia Socket socket = new Socket(addr, NetworkServer.PORT); try { //utworzenie strumieni ObjectOutputStream out = new ObjectOutputStream( socket.getOutputStream()); //transmisja out.writeObject(new String("Hello!")); out.flush(); } finally { //zamkniecie polaczenia socket.close(); }
Klasa ServerSocket • Klasa ServerSocket udostępnia mechanizmy komunikacji strumieniowej dla serwera. Reprezentuje gniazdo, na którym serwer oczekuje pewnego żądania od podłączonego klienta, wykonuje pewne operacje oparte na tym żądaniu a następnia zwraca ich wynik do klienta
Klasa ServerSocket - Konstruktory • ServerSocket() — utworzenie gniazda bez nadanej nazwy (bez dowiązania). • ServerSocket(int port) — utworzenie gniazda z przypisanym domyślnym adresem IP oraz podanym numerem portu. • ServerSocket(int port, int backlog) — utworzenie gniazda na podanym numerze portu z określeniem maksymalnej długo´sci kolejki oczekuj ˛acych ˙z ˛ada´n. • ServerSocket(int port, int backlog, InetAddress bindAddr) — utworzenie gniazda podobnie jak wy˙zej z dodaktowym podaniem adresu IP, jaki ma by´c przpisany do gniazda.
Klasa Socket - Metody • Socket accept()— oczekiwanie na zgłoszenie klientów lub przyjęcie wcześniej zarejestrowanego zgłoszenia • void bind(SocketAddress endpoint)— jawne przypisanie adresu (nadanie nazwy) • void bind(SocketAddress endpoint, int backlog) jawne przypisanie nazwy i określenie maksymalnej długości kolejki oczekujących żądań • void close()— zamknięcie z gniazda
Klasa ServerSocket - Przykład static final int PORT = 1234; //utworzenie serwera ServerSocket s = new ServerSocket(PORT); try { while (true) { //oczekiwanie na nadejscie polaczenia Socket socket = s.accept(); try { //utworzenie watka serwera new ServerThread(socket); } catch (IOException e) { //zamkniecie polaczenia w przypadku wystapienia bledu socket.close(); } }
ServerSocket - obsluga współbierzna • Gniazdo ServerSocket może jednocześnie obsługiwać kilku klientów poprzez utworzenie osobnego wątku dla każdego połączenia.
ServerSocket server_socket; Socket socket; int number = 0; try { server_socket = new ServerSocket(6000); while (true) { socket = server_socket.accept(); System.out.println("Połączono z klientem"); number++; new ServiceThread( socket, number ).start(); } } catch (Exception e) { System.err.println( e.getMessage() ); e.printStackTrace(); }
Klasa DatagramSocket • Klasa reprezentująca gniazdko do wysyłania i odbierania danych datagramowych (UDP). Każdu wysłany lub odebrany pakiet z jednej maszyny na drugą może być przekazany inną drogą i może zostać dostarczony w różnej kolejności.
DatagramSocket - Konstruktory • DatagramSocket() — utworzenie gniazda i wiązanie do adresu lokalnego. • DatagramSocket(int port) — utworzenie gniazda i wiązanie do określonego portu na maszynie lokalnej. • DatagramSocket(int port, InetAddress laddr) — utworzenie gniazda i wiązanie do danego portu na określonej maszynie • DatagramSocket(SocketAddress bindaddr) —utworzenie gniazda i dowiązanie go do podanego adresu.
Datagramsocket - Metody • void bind(SocketAddress addr) — dowiązanie gniazdado podanego addressu. • void close() — zamknięcie gniazda. • void connect(InetAddress address, int port) — związanie gniazda z podanym adresem zdalnym oraz portem • void disconnect() — rozłączenie gniazda.
Klasa DatagramPacket • By wysłać dane przez DatagramSocket należy najpierw stworzyć obiekt DatagramPacket, który reprezentuje bufor, który może być zarówno buforem nadawczym jak i odbiorczym: byte[] buffer = new byte[65508]; InetAddress address = InetAddress.getByName("jenkov.com"); DatagramPacket packet = new DatagramPacket(buffer, buffer.length, address, 9000); • byte[] - dane, które mają zostać wysłane. • byte[].length - długość pakietu • InetAdress - Adres, do którego wysyłamy pakiet • port number - numer portu pod który wysyłamy
DatagramSocket - wysyłanie DatagramSocket datagramSocket = new DatagramSocket(); byte[] buffer = "0123456789".getBytes(); InetAddress receiverAddress = InetAddress.getLocalHost(); DatagramPacket packet = new DatagramPacket( buffer, buffer.length, receiverAddress, 80); datagramSocket.send(packet);
DatagramSocket - odbieranie By odebrać dane przez DatagramSocket należy najpierw stworzyć obiekt DatagramPacket, a następnie przypisać mu odebrane dane przez metode recieve() z DatagramSocket DatagramSocket datagramSocket = new DatagramSocket(80); byte[] buffer = new byte[10]; DatagramPacket packet = new DatagramPacket(buffer, buffer.length); datagramSocket.receive(packet); Przesłane dane mogą zostac zaisane w wywołując metodę getData() byte[] buffer = packet.getData();
MulticastSocket • Multicasting to transmisja grupowa realizowana przez dodatkowe protokoły warstwy aplikacji opierające się na TCP albo UDP. • Klasa MulticastSocket umożliwia komunikowanie się za pomocą technologi multicast. W nagłówku datagramu znajduję się dodatkowe pole TTL (Time - to Live), które określia maksymalną liczbę routerów przez które może przejść pakiet
Multicast • Konstruktory:MulticastSocket ()MulticastSocket (int port) • Podstawowe metody:void joinGroup (InetAddress ia)void leaveGroup (InetAddress ia)void setTimeToLive (int ttl)int getTimeToLive ()
Multicast Wysyłanie • byte[] buf = "01234567890".getBytes();InetAddress ia = InetAddress.getByName("group1.math.uni.lodz.pl");int port = 2468;DatagramPacket dp = new DatagramPacket(buf,buf.length,ia,port);MulticastSocket ms = new MulticastSocket();ms.send(dp);//…
Multicast Odbieranie • MulticastSocket ms = new MulticastSocket(2468);InetAddress ia = InetAddress.getByName("224.0.0.1");byte[] buf = new byte[8192];DatagramPacket dp = new DatagramPacket(buf,buf.length);ms.joinGroup(ia);while (true) { ms.receive(dp); String s = new String(dp.getData(),"utf-8"); //…}