530 likes | 704 Views
Programowanie sieciowe w Javie. Michał Kuciapski m.kuciapski@univ.gda.pl. Gniazda. Gniazda. Gniazda klientów. Koncepcja.
E N D
Programowanie sieciowe w Javie Michał Kuciapski m.kuciapski@univ.gda.pl
Gniazda Gniazda klientów
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); • } • } • }
Gniazda Gniazda serwerów
Cykl życia serwera • Utworzenie na określonym porcie serwera jako obiektu klasy ServerSocket • Oczekiwanie przez serwer na połączenia z portem serwera za pomocą metody accept() zwracające po uzyskaniu połączenia obiekt klasy Socket reprezentujący połączenie pomiędzy klientem i serwerem • W zależności od funkcjonalności serwera pobranie strumienia wejściowego lub wyjściowego • Komunikacja typu klient-serwer do momentu zakończenia połączenia • Zamknięcie połączenia przez klienta, serwer lub obie strony połączenia • Powrót do oczekiwania na połączenie
Tworzenie serwera - konstruktory • Dostępnych są cztery publiczne konstruktory i 2 przeznaczone dla twórców wirtualnych maszyn Javy • Utworzenie serwera wymaga dodania obsługi wyjątków: • BindException – nie można utworzyć gniazda i powiązać go z określonym portem • IOException – problemem połączenia i wymiany danych
Tworzenie serwera - konstruktory • new ServerSocket() • new ServerSocket(int port) • new ServerSocket(int port, int długośćKolejki) • new ServerSocket(int port, int długośćKolejki, • InetAddress interfejs)
Przyjmowanie i zamykanie połączeń • Przyjmowanie połączeń – • public Socket accept() throws IOException • Zamykanie połączeń – • public void close() throws IOException
Tworzenie serwera – przykład 1 • import java.net.*; • import java.io.*; • public class SkanowaniePortowLokalnych { • public static void main(String args[]) • { • for(int port=1; port<100; port++) • try • { • ServerSocket serwer = new ServerSocket(port); • } • catch (IOException e) • { • System.out.println("Na porcie " + port + " działa serwer"); • } • }}
Tworzenie serwera – przykład 1 • import java.net.*; • import java.io.*; • public class SkanowaniePortowLokalnych { • public static void main(String args[]) • { • for(int port=1; port<100; port++) • try • { • ServerSocket serwer = new ServerSocket(port); • } • catch (IOException e) • { • System.out.println("Na porcie " + port + " działa serwer"); • } • }}
Tworzenie serwera – przykład 2 • import java.net.*; • import java.io.*; • public class SerwerZOgraniczeniemKolejki { • public static void main(String args[]) • { • try • { • ServerSocket serwer = new ServerSocket(port, 1, • InetAddres.getHostByName(153.19.122.214)); • } • catch (IOException e) • { • System.out.println("Na porcie " + port + " działa serwer"); • } • }
Pobieranie danych o serwerze • Adresu serwera – • public InetAddress getInnetAddress() • Portu serwera – • public int getLocalPort() • Zespołu danych - • public String toString();
Pobieranie danych o serwerze – przykład • import java.net.*; • import java.io.*; • public class SerwerLosowyPort { • public static void main(String args[]) • { • ServerSocket serwer = null; • for(int i=1; i<5; i++) • try • { • // sprawdzić dla braku podania hosta • serwer = new ServerSocket(0,10, InetAddress.getLocalHost());
Pobieranie danych o serwerze – przykład c.d. • System.out.println("Serwer uruchomiony na hoscie: \n Host: " + • serwer.getInetAddress().getHostName() + "\n Adres: " + • serwer.getInetAddress().getHostAddress() + "\n Port: " + • serwer.getLocalPort()); • //System.out.println("Dane serwera: " + serwer.toString()); • } • catch (IOException e) • { • System.out.println("Na porcie " + serwer.getLocalPort() + " działa • serwer"); • } • } • }
Opcje gniazd serwerów - podstawowe • void setSoTimeout(int milisekundy) throws SocketException – umożliwia ustalenie czasu czekania na połączenie przez metodę accept(). Po upłynięciu limitu czasu zgłasza wyjątek InterruptedException • int getSoTimeout () throws IOException –zwraca bieżącą wartość SO_TIMEOUT
Pobieranie danych o serwerze – przykład • import java.net.*; • import java.io.*; • public class SerwerLimitPoloczenia { • public static void main(String args[]) • { • try • { • Serwer serwer = new ServerSocket(100); • System.out.println("Limit połączenia: " + serwer.getSoTimeout()); • serwer.setSoTimeout(3000); • catch (IOException e) • { • System.out.println("Na porcie " + port + " działa serwer"); • } • }
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
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 serwerPob { • public static void main(String args[]) • { • try • { • ServerSocket server = new ServerSocket(1300); • while(true) • {
Pobieranie danych– przykład c.d • Socket gniazdo = server.accept(); • BufferedReader str = new BufferedReader(new • InputStreamReader(gniazdo.getInputStream())); • System.out.println(str.readLine()); • } • } • catch(IOException e) • { • System.out.println(e.getMessage()); • } • } • }
Wysyłanie danych– przykład • import java.io.*; • import java.net.*; • public class serwerWys { • public static void main(String args[]) • { • try • { • ServerSocket server = new ServerSocket(1310); • while(true) • {
Wysyłanie danych– przykład c.d • gniazdo = server.accept(); • OutputStreamWriter str = new • OutputStreamWriter(gniazdo.getOutputStream()); • str.write("Połączenie sieciowe działa\r\n"); • str.flush(); • gniazdo.close(); • } • } • catch(IOException e) • { • System.out.println(e.getMessage()); • } • } • }
Serwer - przykład • import java.io.*; • import java.net.*; • public class testerKlientow { • public static void main(String args[]) • { • try { • String strona; • System.out.println("Napisz jaki tekst chcesz wysyłać przeglądarkom: "); • BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); • String tekst = br.readLine(); • strona = "HTTP/1.0 200 OK\r\n" + • "Server: Michal Kuciapski 1.0\r\n" + • "Content-length: " + tekst.length() + "\r\n" + • "Content-type: text/plain" + "\r\n\r\n" + • tekst;