470 likes | 624 Views
Programowanie sieciowe w Javie. Michał Kuciapski m.kuciapski@univ.gda.pl. Możliwości sieciowe Javy. Korzyści z zastosowania Javy w programowaniu sieciowym. Język zaprojektowany z myślą o sieci – niezależność od platformy, międzynarodowy zestaw znaków, bezpieczeństwo
E N D
Programowanie sieciowe w Javie Michał Kuciapski m.kuciapski@univ.gda.pl
Korzyści z zastosowania Javy w programowaniu sieciowym • Język zaprojektowany z myślą o sieci – niezależność od platformy, międzynarodowy zestaw znaków, bezpieczeństwo • Bogaty zestaw klas i metod sieciowych • Znaczne uproszczenie obsługi działania sieci
Obszary zastosowań • Pobieranie i wyświetlanie danych – alternatywa dla PHP, CGI, ASP, itd. • Powtarzalne pobieranie i przesyłanie danych • przechowywanie plików • obliczenia równoległe • Formularze • Komunikacja synchroniczna i asynchroniczna • Serwery sieciowe
Obszary zastosowań – c.d. • Przeszukiwanie zasobów sieci • Tworzenie interaktywnych stron: JSP • Handel i bankowość elektroniczna – Java Cryptography Extension • Multimedia – audio/video
Warstwy sieci Aplikacji Aplikacji Transportowa Transportowa Sieciowa Sieciowa Fizyczna
Adresowanie – adresy IP • każdy host w sieci ma przypisany adres IP który jest unikalny przynajmniej w ramach sieci lokalnej • adres IP składa się z 4 oktetów, z których każdy jest cyfrą z zakresu od 0 do 255 • adresy z puli adresów prywatnych: • Klasa A – 10.x.x.x • Klasa B – 172.16.x.x – 172.31.x.x • Klasa C – 192.168.x.x • pula adresów dla testowania – 127.0.x.x
Adresowanie – nazwy przyjazne • przypisywane adresom IP przy wykorzystaniu systemu DNS • FQDN – system jednoznacznego identyfikowania hostów w oparciu o hierarchiczną strukturę DNS – np. bsvc.univ.gda.pl
Porty • umożliwiają wykonywanie wielu zadań „równocześnie” • są elementem abstrakcyjnym – uchwytem do strumienia wejściowego i (lub) wyjściowego • mogą być przydzielone konkretnej usłudze • każdy port jest identyfikowalny liczbą z zakresu od 1 do 65 535 • Zarezerwowane dla znanych usług – 1-1023
Klasa • klasa InetAddress opisuje adres komputera w sieci poprzez nazwę/domenę, np. bsvc.univ.gda.pl oraz poprzez numer IP, np. 153.19.122.213 • obiekty klasy InetAddress są tworzone poprzez metody statyczne, nie są dostępne żadne konstruktory • wszystkie metody muszą zawierać deklaracje lub obsługę wyjątku UnknownHostException
Tworzenie obiektu • InetAddress.getByName(String Nazwa) • InetAddress.getAllByName(String Nazwa) • InetAddress.getLocalHost(String Nazwa)
Przykład import java.net.*; public class Adresy { public static void main(String args[]){ try{ InetAddress lokalny = InetAddress.getLocalHost(); System.out.println("Adres komputera lokalnego: " + lokalny); InetAddress zdalny = InetAddress.getByName("netbeens.org"); System.out.println("Adres komputera www.netbeens.org "+ zdalny);
Przykład c.d. • InetAddress wszystkieZdalny[] = InetAddress.getAllByName("www.netbeens.org"); • System.out.println("Adresy komputera www.netbeens.org to:"); • for(int i=0; i<wszystkieZdalny.length; i++) • { • System.out.println(wszystkieZdalny[i]); • } • } catch (UnknownHostException he) { • he.printStackTrace(); • } • } • }
Metody • Public String getHostName() – zwraca nazwę hosta • Public byte[] getAddress() – zwraca adres hosta jato tablicę byte • Public String getHostAddress() – zwraca nazwę hosta jako tekst • Nie ma dostępnych metod typu setHostName() czy setHostAddress()
Metody – przykład • import java.net.*; • public class daneHosta { • public static void main(String[] args) • { • String nHosta = "localhost"; • try • { • InetAddress host = InetAddress.getByName(nHosta); • byte[] adresIP = host.getAddress(); • String adres = ""; • }
Metody – przykład c.d. • for (int i=0; i<adresIP.length; i++) • { • int przekNaByte = adresIP[i] < 0 ? adresIP[i] + 256 : adresIP[i]; • adres += przekNaByte; • if (i != adresIP.length -1) • adres += "."; • }
Metody – przykład c.d. • System.out.println("Nazwa hosta: " + host.getHostName() + • "\nadres IP poprzez tablicę: " + adres + • "\nadres IP poprzez tekst: " + host.getHostAddress()); • } • catch(UnknownHostException e) • { • System.out.println("Host " + nHosta + "nie istnieje"); • } • }
Gniazda Gniazda klientow
Koncepcja • Gniazda są abstrakcyjnym bytem umożliwiającym pominięcie pisania kodu dla obsługi szczegółów sieci związanych z transmisją danych: rodzajem nośników, rozmiarami, tworzeniem, łączeniem i retransmisją pakietów, sprawdzaniem sekwencji, adresowaniem sieciowym, rutingiem. • Gniazda pozwalają traktować połączenie jako zwykły strumień umożliwiający zapisywanie i pobieranie bajtów (danych).
Możliwe do wykonania operacje • połączyć się ze zdalną maszyną • wysłanie danych • odebranie danych • zamknięcie połączenia • połączyć się ze zdalnym portem • odebrać połączenie od zdalnej maszyny • czekać na nadchodzące dane
Typowy scenariusz połączenia • Utworzenie gniazda • Próba połączenie ze zdalnym hostem • Pobieranie/wysyłanie danych lub zwrócenie błędu • Zamknięcie połączenia
Tworzenie gniazda - konstruktory • Dostępnych jest wiele konstruktorów, z czego 4 są aprobowane, 2 dla wirtualnych maszyn Javy • Utworzenie gniazda wymaga dodania obsługi wyjątków: • UnknownHostException • IOException – związany z problemem połączenia, np.: • Błędy odbioru połączenia • Brak udostępnionego portu • Błędy przekierowań
Tworzenie gniazda - konstruktory • new Socket(String host, int port ) • new Socket(InetAddress host, int port ) • new Socket(String host , int port , InetAddress interfejs , int portLokalny) • new Socket(InetAddress host , int port , InetAddress interfejs , int portLokalny)
Tworzenie gniazda - przykład • import java.net.InetAddress; • import java.net.Socket; • import java.net.UnknownHostException; • import java.io.IOException; • public class TworzenieGniazda { • public static void main(String args[]) • { • try • { • InetAddress lokalny = InetAddress.getByName("83.11.56.140"); • InetAddress zdalny = InetAddress.getByName("bsvc.univ.gda.pl");
Tworzenie gniazda – przykład – c.d. • Socket gniazdo = new Socket(zdalny,80,lokalny,1350); • System.out.println("Na porcie działa serwer"); • } • catch(UnknownHostException e) • { • System.err.println(e); • } • catch(IOException e) • { • System.err.println(e); • } • } • }
Pobieranie informacji z gniazda • InetAddress getInetAddress() • int getPort() • int getLocalPort() • InetAddress getLocalAddress()
Pobieranie informacji z gniazda – przykład 1 String nLokalny = "83.11.56.140"; String nZdalny = "bsvc.univ.gda.pl"; System.out.println("Połączenie z serwerem: " + gniazdo.getInetAddress().getHostName() + " o adresie: " + gniazdo.getInetAddress().getHostAddress() + " na porcie " + gniazdo.getPort() + "\nZ hosta: " + gniazdo.getLocalAddress().getCanonicalHostName() + " o adresie: " + gniazdo.getLocalAddress().getHostAddress() + " na porcie: " + gniazdo.getLocalPort()); Dodatkowy kod dla wcześniejszego przykładu
Pobieranie informacji z gniazda – przykład 2 import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.io.IOException; public class GniazdoInformacje2 { public static void main(String args[]) { String nZdalny = "bsvc.univ.gda.pl"; try { Socket gniazdo = new Socket("www.oracle.com",80); System.out.println(gniazdo.toString()); } catch(UnknownHostException e) { System.err.println(e); } catch(IOException e) { System.err.println(e); } }}
Pobieranie i wysyłanie danych z gniazda • pobieranie danych • InputStream getInputStream() throws IOException • wysyłanie danych • OutputStream getOutputStream() throws IOException • zazwyczaj powyższe strumienie łączy się łańcuchowo z innymi dla wygodniejszego pobierania i przesyłania danych
Pobieranie i wysyłanie danych z gniazda • Przykłady klas obudowujących: • strumień wejściowy: • InputStreamReader(InputStream in) • BufferedReader(Reader in) – dla buforowania • InputStreamReader • Strumień wyjściowy: • PrintWriter(OutputStream out) • OutputStreamWriter(OutputStream out)
Metody związane z pobieraniem danych • Dla klasy InputStream - int read() • Dla klasy InputStreamReader – int read() • Dla klasy BufferedReader – String readLine()
Metody związane z wysyłaniem danych • Dla klasy OutputStream - void write(int dane) throws • IOException • Dla klasy PrintWriter – void print(String dane) • Dla klasy OutputStreamWriter – void write(String dane) throws IOException • void flush() throws IOException – wyczyszcza strumień !!!
Zamykanie strumieni i gniazd • po zakończeniu połączenia należy zamknąć strumienie wejściowe i wyjściowe • w związku z potencjalnym wystąpieniem błędu komunikacji z serwerem należy dodać zamykanie strumieni w obsłudze wyjątków w bloku finally • gniazda jak i strumienie zamyka się poprzez metodę • void close() • Możliwe jest zamknięcie jednostronne gniazda: • void shutDownInput() throws IOException • void shutDownInput() throws IOException
Pobieranie danych - przykład • import java.io.*; • import java.net.*; • public class pobDanych { • public static void main(String args[]) { • try • { • Socket gn = new Socket("localhost", 1310); • InputStreamReader strumWe = new • InputStreamReader(gn.getInputStream()); • BufferedReader br = new BufferedReader(strumWe); • System.out.println(br.readLine()); • }
Pobieranie danych – przykład c.d • catch(UnknownHostException e) • { • System.out.println(e); • } • catch(IOException e) • { • System.out.println(e); • } • } • }
Wysyłanie danych - przykład • import java.io.*; • import java.net.*; • public class wysDanych { • public static void main(String args[]) { • OutputStreamWriter str; • try • { • for (int i=0; i<10;i++) • { Socket gn = new Socket("localhost", 1300); str = new OutputStreamWriter(gn.getOutputStream()); • str.write("Połącznie sieciowe działa \r\n"); • str.flush(); • } • }
Wysyłanie danych – przykład c.d • catch(UnknownHostException e) • { • System.out.println(e); • } • catch(IOException e) • { • System.out.println(e); • } • } • }
Opcje gniazd - podstawowe • void setTcpNoDelay(boolean on) throws IOException – umożliwia natychmiastowe wysyłanie pakietów • boolean getTcpNoDelay() throws IOException • void setSoTimeout(int milisekundy) throws SocketException – umożliwia ustalenie czasu czekania na połączenie • int getSoTimeout () throws SocketException • void setKeepAlive(boolean on) throws SocketException – powoduje okresowe przesyłanie pakietów • boolean getKeepAlive() throws SocketException Java 1.3
Pobieranie i wysyłanie danych - przykład • import java.net.*; • import java.io.*; • public class WhoisKlient { • public static void main(String args[]) • { • int portDomyslny = 43; • String hostDomyslny = "whois.internic.net"; • InetAddress adres; • try • { • adres = InetAddress.getByName(hostDomyslny); • Socket gniazdo = new Socket(adres, portDomyslny);
Pobieranie i wysyłanie danych – przykład c.d. • Writer wys = new OutputStreamWriter(gniazdo.getOutputStream(),"8859_1"); • InputStream wcz = gniazdo.getInputStream(); • for (int i=0;i<args.length;i++) • wys.write(args[i] + " "); • wys.write("\r\n"); • wys.flush(); • int wczZn; • while((wczZn=wcz.read())!=-1) • System.out.print((char)wczZn); • }
Pobieranie i wysyłanie danych – przykład c.d. • catch (UnknownHostException e) • { • System.err.println(e); • } • catch (IOException e) • { • System.err.println(e); • } • } • }