Podaci se šalju preko Interneta u paketima ograničene veličine, koji se nazivaju datagram-ima



Yüklə 458 b.
tarix17.10.2017
ölçüsü458 b.
#5110



podaci se šalju preko Interneta u paketima ograničene veličine, koji se nazivaju datagram-ima

  • podaci se šalju preko Interneta u paketima ograničene veličine, koji se nazivaju datagram-ima

  • datagram ima header i payload

  • header – adresa i port kuda paket ide, adresa i port odakle dolazi itd. ostali podaci neophodni za pouzdani prenos

  • payload – sami podaci



podela podataka u pakete

  • podela podataka u pakete

  • njihovo spajanje na odredištu

  • izgubljeni i oštećeni paketi koje treba ponovo poslati

  • paketi ne stižu dobrim redosledom, pa ih treba preurediti

  • dakle, podela u paketa, generisanje zaglavlja, parsiranje zaglavlja dolazećih paketa, praćenje koji paketi jesu, a koji nisu pristigli – tu ima dosta posla



Srećom, mi o tome ne moramo da brinemo.

  • Srećom, mi o tome ne moramo da brinemo.

  • Soketi omogućavaju programeru da tretira mrežnu konekciju kao još jedan stream u koji može pisati bajtove, odnosno iz kojih može čitati bajtove

  • Soketi štite programera od detalja nižeg nivoa, poput otkrivanja grešaka, veličina paketa, retransmisije paketa, itd.



Soket predstavlja konekciju između dva hosta

  • Soket predstavlja konekciju između dva hosta

  • On može vršiti 7 osnovnih operacija:

    • povezivanje na udaljenu mašinu (connect)
    • slanje podataka (send)
    • primanje podataka (receive)
    • zatvaranje konekcije (close)
    • povezivanje na port (bind to port)
    • osluškivanje dolazećih podataka (listen)
    • prihvatanje konekcija sa udaljenih mašina na povezanom portu


klasa Socket, koju koriste i klijenti i serveri, ima metode koji odgovaraju prvim 4 od prethodnih 7 operacija

  • klasa Socket, koju koriste i klijenti i serveri, ima metode koji odgovaraju prvim 4 od prethodnih 7 operacija

  • Poslednje 3 operacije neophodne su samo serverima, koji čekaju da ih klijenti kontaktiraju. Ove operacije implementirane su klasom ServerSocket



Java programi obično koriste klijentske sokete na sledeći način

  • Java programi obično koriste klijentske sokete na sledeći način

    • program konstruktorom kreira novi soket
    • soket pokušava da se konektuje na udaljeni host
    • nakon što je konekcija uspostavljena, lokalni i udaljeni host uzimaju input i output stream-ove od soketa i koriste te stream-ove da šalju podatke jedan drugome. Konekcija je full-duplex, što znači da oba hosta mogu da primaju i šalju podatke istovremeno. Šta su podaci, zavisi od protokola; različite komande se šalju FTP serveru nego HTTP serveru
    • kada je prenos podataka završen, jedna ili obe strane zatvaraju konekciju. Neki protokoli, poput HTTP 1.0 zahtevaju da se konekcija zatvori nakon obrade svakog zahteva. Drugi, poput FTP dopuštaju obradu većeg broja zahteva jednom konekcijom


java.net.Socket

  • java.net.Socket

  • osnovna klasa za izvršavanje client-side TCP operacija

  • ostale klijentski orijentisane klase koje prave TCP mrežne konekcije (URL, URLConnection, Applet, JEditorPane) pozivaju metode ove klase

  • interfejs koji klasa obezbeđuje programeru su stream-ovi. Stvarno čitanje i pisanje podataka preko soketa vrši se poznatim stream klasama



jednostavni

  • jednostavni

  • svaki dopušta da se zada host i port na koji želimo da se konektujemo

  • host se može zadati kao InetAddress ili String

  • portovi se uvek zadaju kao int vrednosti od 0 do 65535

  • 2 konstruktora takođe zadaju lokalnu adresu i lokalni port sa kojih se šalju podaci (to je možda potrebno kada se želi izabrati jedan određeni mrežni interfejs sa kog se šalju podaci, ako ih je više)

  • postoje i 2 konstruktora koja kreiraju nekonektovane sokete. Oni su korisni kada se žele postaviti opcije soketa pre pravljenja prve konekcije



kreira TCP soket ka zadatom portu i zadatom hostu i pokušava da se konektuje na udaljeni host

  • kreira TCP soket ka zadatom portu i zadatom hostu i pokušava da se konektuje na udaljeni host

  • try{

  • Socket toOReilly = new Socket(”www.oreilly.com”, 80);

  • // send and receive data …

  • }catch(UnkownHostException ex){

  • System.err.println(ex);

  • }catch(IOException ex){

  • System.err.println(ex);

  • }



host je hostname (String). Ako domain name server ne može da razreši hostname ili ne funkcioniše, izbacuje se UnkownHostException

  • host je hostname (String). Ako domain name server ne može da razreši hostname ili ne funkcioniše, izbacuje se UnkownHostException

  • ako soket ne može biti otvoren iz drugih razloga, izbacuje se IOException. Mnogi su razlozi: taj host možda ne prihvata konekcije, dialup konekcija je možda pukla, ili problemi rutiranja sprečavaju pakete da stignu do odredišta

  • ovaj konstruktor ne samo da kreira soket, već takođe pokušava da konektuje soket na udaljeni host, pa se ovaj objekat može koristiti za utvrđivanje da li su dopuštene konekcije na određeni port

  • primer 1 (LowPortScanner)



na Unix sistemima, koji servisi su na kojim portovima može se videti u fajlu /etc/services

  • na Unix sistemima, koji servisi su na kojim portovima može se videti u fajlu /etc/services

  • program na Unix sistemima treba da nađe tačno portove iz tog fajla

  • ne koristite LowPortScanner da probate na mašini koju ne posedujete, jer većina sistem administratora to smatra neprijateljskim činom



radi isto što i prethodni konstruktor (kreira TCP soket ka zadatom portu na zadatom hostu) i pokušava da se konektuje

  • radi isto što i prethodni konstruktor (kreira TCP soket ka zadatom portu na zadatom hostu) i pokušava da se konektuje

  • razlikuje se po tome što koristi InetAddress objekat za zadavanje hosta (umesto hostname)

  • izbacuje IOException ako ne može da se konektuje, ne i UnknownHostException: ako je host nepoznat, saznaćemo kada kreiramo InetAddress objekat



primer upotrebe:

  • primer upotrebe:

  • try{

  • InetAddress oreilly = InetAddress.getByName(”www.oreilly.com”);

  • Socket oreillySocket = new Socket(oreilly, 80);

  • // send and receive data …

  • } catch(UnknownHostException ex){

  • System.err.println(ex);

  • } catch(IOException ex){

  • System.err.println(ex);

  • }

  • U retkim situacijama kada otvarate mnogo soketa na istom hostu, efikasnije je konvertovati hostname u InetAddress i zatim koristiti InetAddress za kreiranje soketa.

  • Primer 2 (HighPortScanner)



… page 8 of 65

  • … page 8 of 65

  • još 2 argumenta: lokalni mrežni interfejs i port

  • ako se za port izabere 0, Java bira slučajan dostupan port između 1024 i 65535

  • ... page 10 of 65

  • konstruktori koji kreiraju sokete koji ne pokušavaju da se konektuju



public InetAddress getInetAddress()

  • public InetAddress getInetAddress()

  • koji je udaljeni host na koji je soket konektovan, ili, ako je konekcija zatvorena, na koji je soket bio konektovan dok je bio konektovan

  • public int getPort()

  • koji je port na udaljenom hostu na koji je soket bio, je ili će biti konektovan

  • public int getLocalPort()

  • (postoje 2 kraja konekcije: remote i local host)

  • Za razliku od remote porta koji je (za klijenta) obično dobro poznat, local port se obično bira od strane sistema u vreme izvršavanja od dostupnih neiskorišćenih portova. Na ovaj način, mnogi različiti klijenti mogu pristupati istom servisu u isto vreme. Local port je ugrađen u IP pakete zajedno sa IP adresom local host-a, tako da server može poslati podatke nazad na pravi port klijenta.

  • public InetAddress getLocalAddress()

  • za koji mrežni interfejs je soket vezan. Ovo se obično koristi na hostu sa većim brojem mrežnih interfejsa

  • primer 3, SocketInfo



vraća ulazni tok koji može čitati podatke iz soketa u program

  • vraća ulazni tok koji može čitati podatke iz soketa u program

  • obično se olančava ovaj InputStream na filter tok ili čitač koji nudi veću funkcionalnost – DataInputStream ili InputStreamReader, npr. pre čitanja ulaza.

  • Zbog poboljšanja performansi, jako je dobra ideja baferisati ulaz olančavanjem na BufferedInputStream i/ili BufferedReader



Sa ulaznim tokom, možemo čitati podatke iz soketa i početi eksperimentisanje sa nekim stvarnim Internet protokolima

  • Sa ulaznim tokom, možemo čitati podatke iz soketa i početi eksperimentisanje sa nekim stvarnim Internet protokolima

  • jedan od najjednostavnijih je daytime

  • klijent otvara soket na portu 13 daytime servera

  • kao odgovor, server šalje vreme u čitljivom formatu i zatvara konekciju

  • ”Wed Nov 12 23:39:15 2003” linija koju je poslao server

  • primer 4, DaytimeClient



DaytimeClient čita hostname daytime servera iz komandne linije i koristi ga za konstruisanje novog Soketa koji se konektuje na port 13 servera

  • DaytimeClient čita hostname daytime servera iz komandne linije i koristi ga za konstruisanje novog Soketa koji se konektuje na port 13 servera

  • ako se izostavi hostname, the National Institute of Standards and Technology server na time.nist.gov se koristi

  • klijent zatim poziva theSocket.getInputStream() da dobije ulazni tok od soketa, i smešta taj tok u promenljivu timeStream

  • pošto daytime protokol specifikuje ASCII, DaytimeClient ne olančava čitač na tok. On samo čita bajtove u StringBuffer, jedan po jedan, prekidajući kada server zatvori konekciju pošto protokol to od njega zahteva.



vremenski serveri na različitim host-ovima koriste različite formate.

  • vremenski serveri na različitim host-ovima koriste različite formate.

  • daytime protokol ne određuje format u kome se vraća vreme, osim da bude čitljiv

  • zato, teško je konvertovati karaktere koje vrati server u Java Date na pouzdan način.

  • Ako želimo da kreiramo Date objekat na osnovu vremena na serveru, lakše je koristiti time protokol iz RFC 868, jer on određuje format vremena



Kada se čitaju podaci sa mreže, bitno je imati na umu da ne koriste svi protokoli ASCII, čak ni tekst

  • Kada se čitaju podaci sa mreže, bitno je imati na umu da ne koriste svi protokoli ASCII, čak ni tekst

  • npr, time protokol zadat u RFC 868 zadaje da se vreme šalje kao broj sekundi od ponoći 1. januara 1900 po Griniču (GMT)

  • Međutim, to se ne šalje kao ASCII string ”2,524,521,600” ili ”-1297728000”, već kao 32-bitni, neoznačeni, big-endian binarni broj



RFC podrazumeva da znamo da svi mrežni protokoli koriste big endian brojeve

  • RFC podrazumeva da znamo da svi mrežni protokoli koriste big endian brojeve

  • primer 5 (TimeClient)

  • Pošto ovo nije tekst, naš program ne može čitati odgovor servera pomoću Reader-a niti bilo koje vrste readLine() metoda.

  • Java program koji se konektuje na time servere mora čitati neobrađene bajtove i interpretirati ih na odgovarajući način

  • U ovom primeru, taj posao komplikuje nedostatak 32-bitnog neoznačenog celobrojnog tipa u Javi.

  • Zato, bajtovi se moraju čitati jedan po jedan i ručno konvertovati u long korišćenjem bitskih operatora << i |.

  • Kada se radi o drugim protokolima, oni mogu baratati formatima podataka koji su još čudniji za Javu, npr. nekoliko mrežnih protokola koristi 64-bitne brojeve u fiksnom zarezu. Tu nema prečice koja će rukovati svim mogućim slučajevima. Prosto, mora se iskodirati sva matematika neophodna za rukovanje podacima u onom formatu koji server pošalje.



program čita hostname servera i opcioni port iz komandne linije i koristi ih za konstruisanje novog Socket objekta koji se konektuje na taj server

  • program čita hostname servera i opcioni port iz komandne linije i koristi ih za konstruisanje novog Socket objekta koji se konektuje na taj server

  • Ako korisnik izostavi hostname, koristi se time.nist.gov

  • podrazumevani port je 37

  • klijent zatim poziva theSocket.getInputStream() da dobije ulazni tok, koji smešta u prom. raw



4 bajta se čitaju iz ovog toka i koriste za konstruisanje long-a koji predstavlja vrednost ta 4 bajta interpretiranu kao 32-bitni neoznačeni ceo broj

  • 4 bajta se čitaju iz ovog toka i koriste za konstruisanje long-a koji predstavlja vrednost ta 4 bajta interpretiranu kao 32-bitni neoznačeni ceo broj

  • ovo daje broj sekundi proteklih od 12:00 A.M. January 1, 1900 GMT (time protocol epoch)

  • 2,208,988,800 sekundi se oduzima od tog broja da bi se dobio broj sekundi proteklih od 12:00 A.M. January 1, 1970 GMT (Java Date class epoch)

  • ovaj broj se množi sa 1000 da bi se konvertovao u milisekunde

  • konačno, taj broj milisekundi konvertuje se u Date objekat koji se štampa kako bi prikazao tekuće vreme i datum



vraća neobrađeni OutputStream za pisanje podataka iz naše aplikacije drugom kraju soketa

  • vraća neobrađeni OutputStream za pisanje podataka iz naše aplikacije drugom kraju soketa

  • obično olančavamo ovaj tok klasama DataOutputStream ili OutputStreamWriter pre njegovog korišćenja

  • Za poboljšanje performansi, dobra ideja je baferisati ga, takođe.



Writer out;

  • Writer out;

  • try{

  • Socket http = new Socket(”www.oreilly.com”,80);

  • OutputStream raw = http.getOutputStream();

  • OutputStream buffered = new BufferedOutputStream(raw);

  • out = new OutputStreamWriter(buffered, ”ASCII”);

  • out.write(”GET / HTTP 1.0\r\n\r\n”);

  • // read the server response …

  • }

  • catch(Exception ex){

  • System.err.println(ex);

  • }

  • finally{

  • try{

  • out.close();

  • }

  • catch(Exception ex){}

  • }



echo protokol, definisan u RFC 862, jedan je od najjednostavnijih interaktivnih TCP servisa

  • echo protokol, definisan u RFC 862, jedan je od najjednostavnijih interaktivnih TCP servisa

  • klijent otvara soket na portu 7 echo servera i šalje podatke

  • server šalje podatke nazad

  • ovo se nastavlja dok klijent ne zatvori konekciju

  • echo protokol je koristan za testiranje mreže, kako bismo bili sigurni da podaci nisu izopačeni  pogrešnim ponašanjem rutera ili firewall-a.



primer koristi getOutputStream() i getInputStream() da implementira jednostavni echo klijent.

  • primer koristi getOutputStream() i getInputStream() da implementira jednostavni echo klijent.

  • korisnik kuca ulaz u komandnoj liniji, koji se zatim šalje serveru

  • server ga vraća nazad

  • program se završava kada korisnik ukuca tačku u posebnoj liniji

  • echo protokol ne određuje kodiranje karaktera. Zapravo, on zadaje da su podaci poslati serveru tačno oni koje server vraća. Server vraća neobrađene bajtove, ne karaktere koje oni predstavljaju. Tako, ovaj program koristi podrazumevano karaktersko kodiranje i line separator klijentskog sistema za čitanje iz System.in, slanje podataka udaljenom sistemu i ispis izlaza na System.out.

  • Kako echo server vraća upravo ono što je poslato, to je kao da se server dinamički podešava prema klijentskim konvencijama za karaktersko kodiranje i prelom linija.

  • Zato, koriste se uobičajene klase i metodi poput PrintWriter i readLine() koje bi u opštem slučaju bile previše nepouzdane



novi Socket objekat, theSocket, kreira se na portu 7

  • novi Socket objekat, theSocket, kreira se na portu 7

  • InputStream soketa vraća se metodom getInputStream() i olančava na InputStreamReader, a ovaj na BufferedReader nazvan networkIn koji čita odgovore servera

  • Pošto ovaj klijent takođe treba da čita ulaz korisnika, on kreira drugi BufferedReader, koji se zove userIn i čita iz System.in

  • Dalje, EchoClient poziva theSocket.getOutputStream() da dobije izlazni tok soketa theSocket, koji se koristi za konstruisanje novog PrintWriter objekta out.

  • Podaci se čitaju iz userIn i pišu na out.

  • Nakon što se podaci pošalju echo serveru, networkIn čeka odgovor.

  • Kada odgovor stigne, on se štampa na System.out.

  • Teoretski, klijent bi mogao da čeka na odovor koji nikada ne stiže. Međutim, to nije verovatno ako se može napraviti konekcija, pošto TCP protokol proverava loše pakete i automatski traži od servera zamene. Za implementiranje UDP echo klijenta (glava 13) potreban je drugačiji pristup jer UDP ne vrši kontrolu grešaka.



primer je linijski-orijentisan

  • primer je linijski-orijentisan

  • on čita liniju iz konzole, šalje je serveru, i čeka da pročita liniju koju mu ovaj vrati

  • međutim, echo protokol to ne zahteva

  • on vraća svaki bajt pošto ga primi

  • nije mu stalo da ti bajtovi predstavljaju karaktere u istom kodiranju ili da budu podeljeni u linije

  • Java ne dopušta da se konzola prebaci u ”neobrađeni” mod, gde se svaki karakter čita čim se ukuca umesto čekanja da korisnik pritisne Enter.

  • Za razliku od mnogih protokola, echo ne zahteva da klijent pošalje zahtev, a onda čeka na pun odgovor servera pre nego što pošalje još podataka. Najjednostavniji način za rukovanje takvim protokolom u Javi je smestiti mrežni ulaz i izlaz u odvojene niti.



ovo je skoro sve što je potrebno znati o soketima

  • ovo je skoro sve što je potrebno znati o soketima

  • kada se piše klijentska aplikacija, skoro sav posao je rukovanje tokovima i interpretiranje podataka

  • sa samim soketima se radi jednostavno (svi teški delovi skriveni su od programera)



primeri do sada podrazumevali su da se soketi sami zatvaraju i nisu radili ništa da počiste za sobom

  • primeri do sada podrazumevali su da se soketi sami zatvaraju i nisu radili ništa da počiste za sobom

  • tačno je da se soket automatski zatvara kada se zatvori jedan od njegova dva stream-a, kada se završi program, ili kada ga počisti garbage collector.

  • Međutim, loša je praksa pretpostavljati da će sistem zatvarati naše sokete, posebno za programe koji se mogu izvršavati neograničeno dugo

  • u programima koji intenzivno koriste sokete, poput web browser-a, sistem može dostići max broj otvorenih soketa pre nego što ih pokupi garbage collector.

  • primeri 1 i 2 su naročito loši u tom pogledu, pošto može proteći puno vremena dok program prođe sve portove



kada završite sa soketom, treba pozvati njigov close() metod za diskonektovanje

  • kada završite sa soketom, treba pozvati njigov close() metod za diskonektovanje

  • idealno, on se stavlja u finally blok tako da se soket zatvara bez obzira da li je izbačen izuzetak ili ne

  • sintaksa je pravolinijska



Socket connection = null;

  • Socket connection = null;

  • try{

  • connection = new Socket(”www.oreilly.com” , 13);

  • // interact with the socket…

  • } // end try

  • catch(UnknownHostException ex){

  • System.err.println(ex);

  • }

  • catch(IOException ex){

  • System.err.println(ex);

  • }

  • finally{

  • if(connection != null) connection.close();

  • }



nakon što je soket zatvoren, njegov InetAddress, broj porta, lokalna adresa i lokalni broj porta su još uvek dostupni preko odgovarajućih get*() metoda

  • nakon što je soket zatvoren, njegov InetAddress, broj porta, lokalna adresa i lokalni broj porta su još uvek dostupni preko odgovarajućih get*() metoda

  • međutim, iako je moguće zvati getInputStream() ili getOutputStream(), pokušaj čitanja ili pisanja podataka dovodi do izbacivanja IOException

  • primer 7, revizija PortScanner programa koja zatvara svaki soket kada završi sa njim. Ne zatvara sokete koji nisu uspeli da se konektuju. Pošto oni nisu nikada otvoreni, ne moraju se zatvoriti. Zapravo, kada konstruktor ne uspe, connection ima vrednost null.



vraća true ako je soket zatvoren, false inače

  • vraća true ako je soket zatvoren, false inače

  • ako niste sigurni kakvo je stanje soketa, možete proveriti ovim metodom, radije nego da reskirate IOException

  • if(socket.isClosed())

  • // do something ...

  • else

  • // do something else

  • međutim, ovo nije savršen test. ako soket nikada nije bio konektovan, isClosed() vraća false, čak i kada soket nije otvoren



ime može da zavara

  • ime može da zavara

  • ovaj metod ne kaže da li je soket trenutno konektovan na udaljeni host, već da li je soket ikada bio konektovan na udaljeni host.

  • ako je soket bio u mogućnosti da se konektuje na udaljeni host ikada, metod vraća true, čak i ako je soket zatvoren

  • za proveru da li je soket trenutno otvoren, mora se proveriti da isConnected() vraća true i isClosed() vraća false.

  • boolean connected = socket.isConnected() && !socket.isClosed();



odnosi se na lokalni kraj soketa

  • odnosi se na lokalni kraj soketa

  • metod kaže da li je soket uspešno povezan na izlazni port lokalnog sistema. To u praksi nije vrlo važno. Postaće važnije kod serverskih soketa



close() metod zatvara oba input i output soketa

  • close() metod zatvara oba input i output soketa

  • povremeno, želimo da zatvorimo samo pola konekcije, bilo izlaz bilo ulaz

  • public void shutdownInput() throws IOException

  • public void shutdownOutput() throws IOException

  • Ovo ne zatvara soket. Ali podešava tok povezan na njega da misli da je kraj toka. Dalje čitanje iz ulaznog toka vraća -1. Dalje pisanje u izlazni tok izbacuje IOException.

  • Mnogi protokoli, poput finger, whois, HTTP počinju tako što klijent šalje zahtev serveru, a zatim čita odgovor. Moguće je zatvoriti izlaz nakon što klijent pošalje zahtev.



Sledeći fragment koda šalje zahtev HTTP serveru i onda zatvara izlaz, pošto neće više ništa pisati serveru preko tog soketa

  • Sledeći fragment koda šalje zahtev HTTP serveru i onda zatvara izlaz, pošto neće više ništa pisati serveru preko tog soketa

  • Socket connection = null;

  • try{

  • connection = new Socket(”www.oreilly.com”, 80);

  • Writer out = new OutputStreamWriter(connection.getOutputStream, ”8859_1”);

  • out.write(”GET / HTTP 1.0\r\n\r\n”);

  • out.flush();

  • connection.shutdownOutput();

  • // read the response …

  • }

  • catch(IOException ex){}

  • finally{

  • try{

  • if(connection!=null) connection.close();

  • }

  • catch(IOException ex){}

  • }



primetite da iako zatvorite pola, ili obe polovine konekcije, još uvek treba da zatvorite soket kada završite sa njim.

  • primetite da iako zatvorite pola, ili obe polovine konekcije, još uvek treba da zatvorite soket kada završite sa njim.

  • shutdown metodi prosto utiču na tokove soketa. Oni ne oslobađaju resurse pridružene soketu poput porta koji on zauzima

  • public boolean isInputShutdown()

  • public boolean isOutputShutdown()

  • ovi metodi se mogu koristiti (radije nego isConnected() i isClosed()) za određeniju proveru da li se može pisati ili čitati iz soketa



9.3.4 Setting Socket Options

  • 9.3.4 Setting Socket Options

  • page 39 of 65

  • 9.6 Examples



Yüklə 458 b.

Dostları ilə paylaş:




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©genderi.org 2024
rəhbərliyinə müraciət

    Ana səhifə