mrezno racunarstvo udp datagrams and sockets

101
1 Mre Mre žno računarstvo žno računarstvo poglavlje 13. poglavlje 13. UDP Datagrams and UDP Datagrams and Sockets Sockets

Upload: markoo12

Post on 05-Nov-2015

244 views

Category:

Documents


5 download

DESCRIPTION

dsda

TRANSCRIPT

  • *Mreno raunarstvopoglavlje 13.UDP Datagrams and Sockets

  • *Uvodna priaU prethodnim poglavljima razmatrane su aplikacije koje koristeTCP protokol.TCP je dizajniran za pouzdan transfer podataka. Ako se prilikom transfera podaci otete ili izgube, TCP obezbeuje da se ponovo poalju, ako ne stiu odgovarajuim redom, TCP ih preuredi, ako podaci stiu prebrzo, TCP uspori tako da se paketi ne gube.Meutim, cena ove pouzdanosti je brzina. Uspostavljanje i raskidanje konekcije moe trajati prilino vremena, posebno za protokole kao to je HTTP, koji zahteva puno kratkih transfera

  • *UDPUser Datagram Protocol (UDP) je alternativni protokol za slanje podataka preko IP, koji je vrlo brz, ali nije pouzdanKada se poalju podaci, nema naina da se sazna da li su stigli ili da li su stigli redosledom kojim su poslati. Meutim, podaci koji stiu, stiu brzo

  • *UDP protokolZato bi iko eleo da koristi nepouzdani protokol?UDP oigledno nije dobar za aplikacije poput FTP.Meutim, postoje mnoge vrste aplikacija u kojima je brzina vanija od ispravnog primanja svakog pojedinanog bita.real-time audio ili video

  • *U drugim aplikacijama, mogu se implementirati testovi pouzdanosti u application sloju. Npr. ako klijent poalje kratak UDP zahtev serveru, moe pretpostaviti da je paket izgubljen ako ne dobije odgovor u dogovorenom periodu. To je jedan nain na koji funkcionie Domain Name Server (DNS). DNS takoe moe raditi i preko TCP. ...

  • * Razlika izmeu TCP i UDP esto se objanjava analogijom izmeu telefonskog i potanskog sistema.TCP je poput telefonskog sistema. Kada pozovete broj, telefon se javi i konekcija izmeu dve strane je uspostavljena. Dok priate, znate da druga strana uje vae rei onim redom kojim ih priate. Ako je telefon zauzet ili se niko ne javlja, odmah to znate.UDP, suprotno, je kao potanski sistem. aljete potu na neku adresu. Veina pisama stigne, ali neka mogu biti izgubljena. Pisma verovatno stiu redom kojim su poslata, ali ne postoji garancija. to smo dalje od primaoca, verovatnije je da e pota biti izgubljena ili stii nekim drugim redosledom. Ako je to problem, moemo pisati redne brojeve a zatim traiti od primalaca da ih urede i poalju pismo koje kae koja pisma su stigla tako da moemo ponovo da poaljemo ona koja nisu. Meutim, mi i primalac to moramo da dogovorimo unapred. Pota to nee uraditi za nas.

  • *I telefonski i potanski sistem imaju svoje korisnike. Iako se bilo koji moe koristiti za skoro svaku komunikaciju, u nekim sluajevima jedan je definitivno superiorniji od drugog. Isto vai i za UDP i TCP.TCP aplikacije su uobiajenije od UDP.Multicasting se zasniva na UDP: multicast soket je jednostavna varijanta UDP soketa

  • *Java implementacija UDP-a podeljena je u dve klase: DatagramPacket i DatagramSocket.Klasa DatagramPacket puni bajtovima podataka UDP pakete koji se zovu datagram-ima i doputa da ispraznimo datagram-e koje primimo.DatagramSocket alje i prima UDP datagrame. Da bismo poslali podatke, stavimo ih u DatagramPacket i poaljemo paket koristei DatagramSocket. Da primimo podatke, primimo DatagramPacket objekat od DatagramSocket-a, a zatim proitamo sadraj paketa.

  • *Sami soketi su vrlo jednostavni.U UDP, sve o datagramu, ukljuujui adresu na koju je upuen, ukljueno je u sam paket. Soket samo treba da zna lokalni port na kome slua ili aljeOva podela posla je u suprotnosti sa klasama Socket i ServerSocket koje koristi TCP.Prvo, UDP nema ideju o jedinstvenoj konekciji izmeu hostova. Jedan soket alje i prima sve podatke upuene ka ili od porta bez ikakve brige ko je udaljeni host. Jedan DatagramSocket moe slati podatke i primati podatke od mnogo nezavisnih hostova. Soket nije posveen jednoj konekciji, kao to je to sluaj u TCP. Zapravo, UDP nema nikakav koncept konekcije izmeu dva hosta; on jedino poznaje pojedinane datagrame. Otkrivanje ko alje podatke je odgovornost aplikacije.

  • *Klasa DatagramPacketUDP datagrami dodaju jako malo IP datagramima od kojih nastaju. UDP zaglavlje dodaje svega 8 bajtova IP zaglavlju.UDP zaglavlje ukljuuje port brojeve izvorita i odredita, duinu svega to prati IP zaglavlje i opcionu kontrolnu sumuPoto se portovi zadaju kao 2-bajtni neoznaeni brojevi, 65536 razliitih moguih UDP portova je dostupno po hostu. Oni se razlikuju od 65536 razliitih TCP portova po hostu.Duina je takoe 2-bajtni neoznaeni integer, pa je broj bajtova u datagram-u ogranien na 65536-8 za zaglavlje. Meutim, to je teoretska granica. U praksi je veliina znatno manjaKontrolna suma je opciona i programi iz aplikacionog sloja je ne koriste niti joj mogu pristupiti. Ako se kontrolna suma ne poklopi, native mreni software tiho odbaci datagram, ne obavetavajui o tome ni poiljaoca ni primaoca. Na kraju krajeva, UDP je nepouzdan protokol.

  • *Koliina podataka u UDP datagramu je na mnogim platformama ograniena na 8192 bajta (8K)Implementacije ne moraju prihvatiti datagrame sa vie od 576 bajtova ukupno, ukljuujui podatke i zaglavlja.Zato, treba biti jako obazriv sa programima koji alju ili primaju UDP pakete sa vie od 8K podataka. Vei deo vremena, vei paketi se jednostavno skrate na 8K. Za maksimalnu bezbednost, data deo UDP paketa treba da bude 512 bajtova ili manji, iako se to ogranienje negativno odraava na performanse u poreenju sa paketima vee veliine(ovo je problem i za TCP datagrame, ali stream-based API koji obezbeuju Socket i ServerSocket potpuno titi programere od ovih detalja)

  • *U Javi, UDP datagram je predstavljen instancom klase DatagramPacketOva klasa obezbeuje metode za dohvatanje i postavljanje izvorine i odredine adrese u IP zaglavlju, za dohvatanje i postavljanje izvorinog i odredinog porta, za dohvatanje i postavljanje podataka i duine podatakaPreostala polja zaglavlja nisu pristupana Java kodu

  • *KonstruktoriDatagramPacket koristi razne konstruktore u zavisnosti od toga da li e se paket koristiti za slanje podataka ili njihovo primanje (to je malo neuobiajeno korienje razliitih konstruktora za kreiranje objekata koji e se koristiti u razliitim kontekstima)Svi konstruktori (njih 6) primaju kao argumente byte niz koji uva podatke datagrama i broj bajtova u tom nizu koji se koristi za podatke datagrama. Kada elimo da primimo datagram, trebaju nam samo ti argumenti i jo niz treba da bude prazan. Kada soket prima datagram iz mree, podatke datagrama smeta u niz DatagramPacket objekta, do duine koju smo zadali.

  • *Drugi skup konstruktora se koristi za kreiranje datagrama koje aljemo preko mree. Kao i prvi, ovi konstruktori zahtevaju bafer-niz i duinu, ali takoe i InetAddress i port na koji se paket alje. U ovom sluaju, konstruktoru se prosleuje byte niz koji sadri podatke koje elimo da poaljemo, kao i odredina adresa i port na koji se paket alje. DatagramSocket ita odredinu adresu i port iz paketa. Adresa i port se ne smetaju u soket, kao u TCP.

  • *Konstruktori za primanje datagrama2 konstruktora kreiraju novi DatagramPacket objekat za primanje podataka iz mreepublic DatagramPacket(byte[] buffer, int length)public DatagramPacket(byte[] buffer, int offset, int length)Kada soket primi datagram, smeta podatke datagrama u buffer poev od buffer[0] (prvi), odnosno buffer[offset] (drugi) sve dok se ceo paket ne proita ili dok se ne upie length bajtova u buffer.length mora biti manje ili jednako od buffer.length-offsetIllegalArgumentException (RuntimeException na kod nije duan da ga hvata)sledei fragment koda kreira novi DatagramPacket za primanje do 8192 bajta: byte[] buffer = new byte[8192]; DatagramPacket dp = new DatagramPacket(buffer, buffer.length);

  • *8KKonstruktor ne mari za veliinu bafera i dopustio bi da kreiramo DatagramPacket sa megabajtima podataka. Ali...(vai ona prethodna pria o ogranienjima) ne treba kreirati DatagramPacket objekte sa vie od 8192 bajtova podataka

  • *Konstruktori za slanje datagrama4 konstruktora kreiraju novi DatagramPacket objekat za slanje podataka preko mreepublic DatagramPacket(byte[] data, int length, InetAddress destination, int port)public DatagramPacket(byte[] data, int offset, int length, InetAddress destination, int port)public DatagramPacket(byte[] data, int length, SocketAddress destination, int port)public DatagramPacket(byte[] data, int offset, int length, SocketAddress destination, int port)

  • *Svaki od ovih konstruktora kreira novi DatagramPacket koji e biti poslat drugom hostu.Paket se puni sa length bajtova niza data poev od offset ili 0, ako se ne koristi offset.IllegalArgumentException (length>data.length)length bajtova podataka se alje preko mree

  • *Izbor veliine Datagram-aKoliina podataka kojom se puni paket zavisi od situacije. Neki protokoli diktiraju veliinu paketa. Npr. rlogin odailje svaki karakter udaljenom sistemu skoro odmah poto ga korisnik otkuca. Tu su paketi kratki: jedan bajt podataka i nekoliko bajtova zaglavlja. Druge aplikacije nisu takve: npr. file transfer je mnogo efikasniji sa veim baferima; jedini zahtev je da podelimo fajl u pakete ne vee od maksimalne dozvoljene veliine paketa.Nekoliko faktora je ukljueno u izbor optimalne veliine paketa. Ako je mrea jako nepouzdana, bolji su manji paketi poto su manje anse da budu oteeni u putu. S druge strane, vrlo brzi i pouzdani LAN-ovi treba da koriste pakete to je mogue vee. 8K = 8192 bajta je dobar kompromis za mnoge vrste mrea

  • *Uobiajeno je konvertovati podatke u byte niz i smestiti ih u data pre kreiranja DatagramPacket, ali nije apsolutno neophodno.Promene niza data nakon kreiranja datagrama i pre njegovog slanja menjaju podatke u datagramu (podaci se ne kopiraju u privatni bafer). U nekim aplikacijama, moe se iskoristiti prednost ovoga. Npr. moemo smestiti u data podatke koji se vremenom menjaju i slati tekui datagram (sa najtazijim podacima) svakog minuta. Meutim, vanije je osigurati da se podaci ne menjaju kada to ne elimo. Ovo je posebno vano kada nam je program multithreaded i razne niti mogu pisati podatke u bafer data. Ako je to sluaj, vri se sinhronizacija data promenljive ili kopiraju podaci u privremeni bafer pre konstruisanja DatagramPacket-a.

  • *Sledei fragment kreira DatagramPacket napunjen podacima This is a test u ASCII-ju. Paket je upuen portu 7 (echo port) na hostu www.ibiblio.org:String s = This is a test;byte[] data = s.getBytes(ASCII);

    try{ InetAddress ia = InetAddress.getByName(www.ibiblio.org); int port = 7; DatagramPacket dp = new DatagramPacket(data, data.length, ia, port); // send the packet }catch(IOException ex){} Vei deo vremena, najtei deo posla oko kreiranja novog DatagramPacket-a je prevoenje podataka u byte niz. Poto ovaj fragment eli da poalje ASCII-string, koristi getBytes() metod klase java.lang.String.Klasa java.io.ByteArrayOutputStream takoe moe biti jako korisna za pripremu podataka za ukljuivanje u datagrame.

  • *get*() metodi6 metoda za dohvatanje razliitih delova datagrama: stvarnih podataka plus nekoliko polja iz zaglavljaovi metodi se uglavnom koriste za datagrame primljene iz mreepublic InetAddress getAddress() vraa InetAddress objekat koji sadri adresu udaljenog hosta. Ako je datagram primljen, vraa se adresa maine koja ga je poslala. Ako je datagram kreiran lokalno da bi bio poslat udaljenoj maini, metod vraa adresu hosta na koji je adresiran. Metod se obino koristi da odredi adresu hosta koji je poslao UDP datagram, tako da primalac moe da odgovori

  • *public int getPort() vraa integer koji odreuje udaljeni portpublic SocketAddress getSocketAddress() vraa SocketAddress objekat koji sadri adresu i port udaljenog hosta. Efekat nije znaajno razliit od poziva getAddress() i getPort() ali utedi jedan poziv metoda. Takoe, ako se koristi neblokirajui I/O, klasa DatagramChannel prihvata SocketAddress, ali ne i InetAddress i port.

  • *public byte[] getData() vraa byte niz koji sadri podatke datagrama. esto je potrebno konvertovati bajtove u neki drugi oblik pre nego to postanu korisni za na program. Jedan nain da se to uradi je promeniti byte niz u String korienjem sledeeg String konstruktora:public String(byte[] buffer, String encoding) Prvi argument, buffer, je niz bajtova koji sadri podatke datagrama. Drugi argument sadri ime kodiranja za string, npr. ASCII ili ISO-8859-1 Npr. dati DatagramPacket dp primljen sa mree, moemo konvertovati u String sa:String s = new String(dp.getData(), ASCII);

  • *Ako datagram ne sadri tekst, konvertovanje u Java podatak je komplikovanije. Jedan pristup je konvertovati byte niz koji vrati getData() u ByteArrayInputStream koristei konstruktor:public ByteArrayInputStream(byte[] buffer, int offset, int length) buffer je byte niz koji e se koristiti kao InputStream. Vano je zadati deo buffer-a koji elimo da koristimo kao InputStream korienjem argumenata offset i length. Prilikom konvertovanja datagram podataka u InputStream objekte, offset je ili 0 ili dat metodom getOffset() DatagramPacket objekta a duina je data metodom getLength() DatagramPacket objektanpr.InputStream in = new ByteArrayInputStream(packet.getData(), packet.getOffset(), packet.getLength()); prilikom konstruisanja ByteArrayInputStream-a moraju se zadati offset i length. NE KORISTITI ByteArrayInputStream konstruktor koji prima samo niz kao argument. Niz koji vrati packet.getData() verovatno ima u sebi i prostor koji nije popunjen podacima iz mree. Ovaj prostor moe sadrati proizvoljne sluajne vrednosti koje su se zadesile u nizu prilikom konstruisanja DatagramPacket-a

  • *ByteArrayInputStream moe biti olanan na DataInputStream:DataInputStream din = new DataInputStream(in);podaci se onda mogu itati korienjem DataInputStream-ovih readInt(), readLong(), readChar() i drugih metoda.Naravno, ovo podrazumeva da poiljalac koristi iste formate podataka kao Java to verovatno jeste sluaj ako je on napisan u Javi, a esto je (mada ne nuno) sluaj i inae. (veina modernih raunara koristi isti format pokretnog zareza kao i Java, i veina mrenih protokola odreuje cele brojeve u potpunom komplementu u mrenom poretku bajtova, to se takoe poklapa sa Javinim formatima)

  • *public int getLength() vraa broj bajtova podataka u datagramu. To nije nuno isto kao i duina niza vraenog sa getData(), tj. getData().length. Broj vraen sa getLength() moe biti manji od togapublic int getOffset() vraa poziciju u nizu vraenom sa getData() gde poinju podaci datagrama.Primer 1 (DatagramExample): koristi sve ove metode da odtampa informacije iz DatagramPacket-a. Primer je malo vetaki, jer program kreira DatagramPacket za koji ve zna ta je unutra. ee se ovi metodi koriste na DatagramPacket-u primljenom sa mree, ali za to je potrebna i klasa DatagramSocket

  • *set*() metodinekoliko metoda za promenu podataka, udaljene adrese, udaljenog porta nakon kreiranja datagramaovi metodi mogu biti od znaaja u situaciji kada je kreiranje i garbage collect DatagramPacket-a znaajan udarac za performanse. U nekim situacijama, reusing objekata moe biti znaajno bri od konstruisanja novih: npr za mrenu igru Quake koja alje po datagram za svaki ispaljeni metak, ili svaki centimetar pomeranja. Meutim, neophodno je koristiti veoma brzu konekciju da bi poboljanje bilo uoljivo (jer je i sama mrea spora)

  • *public void setData(byte[] data) menja koristan sadraj UDP datagrama. Moe se koristiti ako se alje veliki fajl (veliki vei nego to moe da stane u jedan datagram) udaljenom hostu. Moe se uzastopno slati isti DatagramPacket objekat, menjajui samo podatke svaki putpublic void setData(byte[] data, int offset, int length) alternativni pristup za slanje velike koliine podataka. Umesto slanja mnotva novih nizova, svi podaci se mogu staviti u jedan niz i slati deo po deo. Primer (kod na sledeem slajdu):

  • *int offset = 0;DatagramPacket dp = new DatagramPacket(bigarray, offset, 512);int bytesSent = 0;while(bytesSent < bigarray.length){ socket.send(dp); bytesSent += dp.getLength(); int bytesToSend = bigarray.length bytesSent; int size = (bytesToSend > 512) ? 512 : bytesToSend; dp.setData(bigarray, bytesSent, size);} S druge strane, ovakav pristup zahteva puno poverenja da e podaci stii, ili alternativno, zanemarivanje posledica njihovog nestizanja. Relativno je teko pridruiti redne brojeve ili druge dodatke za pouzdanost pojedinanim paketima kada se koristi ovaj pristup

  • *public void setAddress(InetAddress remote) menja adresu na koju se alje datagram paket. Doputa da se isti datagram poalje veem broju razliitih primalaca. Npr.String s = Really Important Message;byte[] data = s.getBytes(ASCII);DatagramPacket dp = new DatagramPacket(data, data.length);dp.setPort(2000);String network = 128.238.5.;for((int host = 1; host < 255; host++){ try{ InetAddress remote = InetAddress.getByName(network + host); dp.setAddress(remote); socket.send(dp); }catch(IOException ex){ // slip it; continue with the next host }

  • *Da li je ovo razuman izbor zavisi od aplikacije. Ako elite da poaljete svim raunarima u nekom delu mree, kao to je sluaj u prethodnom fragmentu, verovatno je bolje koristiti lokalnu broadcast adresu i pustiti da mrea odradi posao. Lokalna broadcast adresa se odreuje postavljanjem svih bitova IP adrese nakon ID-ova mree i podmree na 1. Npr. mrena adresa Politehnikog univerziteta je 128.238.0.0. Dakle, broadcast adresa je 128.238.255.255. Slanje datagrama na 128.238.255.255 kopira ga svakom hostu na toj mreiZa ire rasprostranjene hostove, verovatno je bolje koristiti multicasting. Multicasting zapravo koristi istu DatagramPacket klasu koja je ovde opisana. Meutim, koristi razne IP adrese i MulticastSocket umesto DatagramSocket-a. To je opisano u poglavlju14.

  • *public void setPort(int port) menja port na koji je datagram adresiran. Harold ne vidi emu slui ovaj metod Moe da se koristi za port scanner aplikaciju koja pokuava da pronae otvorene portove koji izvravaju odreene UDP-zasnovane servise poput FSP. Druga mogunost bila bi neka vrsta mrene igre ili konferencijskog servera gde se klijenti koji treba da prime istu informaciju izvravaju na razliitim portovima razliitih hostova. U ovom sluaju, setPort() bi se koristio sa setAddress() za promenu destinacije pre ponovnog slanja istog datagrama

  • *public void setAddress(SocketAddress remote) menja adresu i port na koje se alje datagram. Moe se koristiti prilikom odgovaranja. Sledei fragment koda prima datagram paket i odgovara na istu adresu paketom koji sadri ASCII string Hello there:DatagramPacket input = new DatagramPacket(new byte[8192], 8192);socket.receive(input);SocketAddress address = input.getSocketAddress();DatagramPacket output = new DatagramPacket(Hello there.getBytes(ASCII), 11);output.setAddress(address);socket.send(output);

  • *public void setLength(int length) menja broj bajtova podataka u internom baferu koji se smatraju delom datagram podataka nasuprot prosto neispunjenom prostoru. Metod je koristan prilikom primanja datagrama to e biti vieno u nastavku prie. Kada se datagram primi, njegova duina se postavi na duinu dolazeih podataka. Ovo znai da ako pokuamo da primimo drugi datagram u isti DatagramPacket, on je ogranien na ne vie od broja bajtova u prvom. Tj. jednom kada primimo 10-bajtni datagram, svi naredni datagrami bie skraeni na 10 bajtova, jednom kada primimo 9-bajtni, svi naredni bie skraeni na 9-bajtova, itd. Ovaj metod omoguava da se resetuje duina bafera tako da se naredni datagrami ne odsecaju.

  • *Klasa DatagramSocketDa bi se DatagramPacket primio ili poslao, neophodno je otvoriti datagram soket.U Javi, datagram soket se kreira i pristupa mu se korienjem DatagramSocket klaseSvi datagram soketi su vezani za lokalni port, na kome oslukuju dolazee podatke i koji (broj tog porta) smetaju u zaglavlja odlazeih datagramaAko piemo klijent, nije nam bitno koji je lokalni port, pa zovemo konstruktor koji doputa da sistem pridrui neiskorieni port (anonimni port). Broj porta se smeta u sve odlazee datagrame i server e ga koristiti da bi adresirao datagrame odgovoraAko piemo server, klijenti treba da znaju na kom portu server oslukuje dolazee datagrame, pa kada server konstruie DatagramSocket, on zadaje lokalni port na kome oslukuje.U svim ostalim aspektima soketi koje koriste klijenti i serveri su identini: razlikuju se samo po tome da li koriste anonimni (sistemski pridrueni) ili poznati port. Nema razlike izmeu klijentskih i serverskih soketa, kao to je sluaj kod TCP. Ne postoji stvar kao to je DatagramServerSocket.

  • *KonstruktoriDatagramSocket konstruktori se koriste u raznim situacijama, veinom kao i DatagramPacket konstruktoriprvi konstruktor otvara datagram soket na anonimnom lokalnom portudrugi otvara datagram soket na poznatom portu koji oslukuje na svim lokalnim mrenim interfejsimatrei otvara datagram socket na poznatom portu na zadatom mrenom interfejsu+ konstruktor koji omoguuje zadavanje mrenog interfejsa i porta preko SocketAddressSvi konstruktori rukuju samo lokalnom adresom i portomUdaljena adresa i port smeteni su u DatagramPacket, NE u DatagramSocket. Zapravo, jedan DatagramSocket moe slati i primati datagrame od veeg broja udaljenih hostova i portova

  • *public DatagramSocket() throws SocketException kreira soket koji je vezan za anonimni portnpr.try{ DatagramSocket client = new DatagramSocket(); // sent packets }catch(SocketException ex){System.err.println(ex);}ovaj konstruktor treba koristiti u klijentu koji zapoinje konverzaciju sa serverom. U ovom scenariju, ne interesuje nas broj porta za koji je soket vezan, jer server e poslati svoj odgovor portu sa kog datagram potie.Preputanje sistemu da pridrui port znai da ne moramo da brinemo o pronalaenju slobodnog porta. Ako, iz nekog razloga, treba da znamo broj porta, moemo ga nai metodom getLocalPort() koji je opisan kasnije u tekstuIsti soket moe primati i datagrame koje mu server alje nazadSocketException se izbacuje ako se soket ne moe kreirati. Neuobiajeno je da ovaj konstruktor izbaci izuzetak; teko je zamisliti situaciju u kojoj soket ne moe biti otvoren poto sistem bira lokalni port

  • *public DatagramSocket(int port) throws SocketExceptionkreira soket koji oslukuje dolazee datagrame na zadatom portukoristite ovaj konstruktor za pisanje servera koji oslukuje na poznatom portuako server oslukuje na anonimnim portovima, klijenti nee biti u mogunosti da ga kontaktirajuSocketException se izbacuje ako se soket ne moe kreirati. Postoje 2 uobiajena razloga za to: zadati port je ve u upotrebi ili pokuavate da se konektujete na port nii od 1024, a nemate odgovarajue privilegije (root na Unix-u)

  • *TCP i UDP portovi nisu u vezi. 2 servera i klijenta koji nisu u vezi mogu koristiti isti broj porta ako jedan koristi UDP, a drugi TCP.Primer 2: UDPPortScanner trai UDP portove koji se koriste na local hostu. Port je u upotrebi ako DatagramSocket konstruktor izbaci izuzetakPretrauju se portovi poev od 1024 zbog Unix-ovog ogranienja. Lako se moe proiriti i za ostale portove (ako imate root privilegije ili radite pod Windows-om)brzina kojom se primer izvrava jako zavisi od brzine maine i njene UDP implementacije2 minuta na prosenom SPARCstation, manje od 12 sekundi na 1GHz TiBook, 7 sekundi na 1.4GHz Athlon sistemu pod Linux-om, i oko sat na PowerBook 5300 pod MacOS 8.Mnogo tee je skenirati UDP portove na udaljenoj maini nego skenirati TCP portove. Za TCP port uvek postoji neka indikacija da je primio Va TCP paket. UDP ne obezbeuje takve garancije. Da biste utvrdili da UDP server oslukuje, morate mu poslati paket koji e on prepoznati i odgovoriti na njega

  • *public DatagramSocket(int port, InetAddress interface) throws SocketExceptionkonstruktor se primarno koristi na multihomed hostovimakreira soket koji oslukuje dolazee datagrame na zadatom portu i mrenom interfejsupostoje 3 uobiajena razloga zbog kojih konstruktor ne uspeva: zadati port je ve u upotrebi, pokuavate da se konektujete na port ispod 1024, a niste root na Unix sistemu ili interface nije adresa nijednog mrenog interfejsa na Vaem sistemu

  • *public DatagramSocket(SocketAddress interface) throws SocketExceptionslino kao prethodni, osim to se adresa interfejsa i port itaju iz SocketAddressnpr. sledei fragment kreira soket koji slua samo na lokalnoj loopback adresi:SocketAddress address = new InetSocketAddress(127.0.0.1, 9999);DatagramSocket socket = new DatagramSocket(address);protected DatagramSocket(DatagramSocketImpl impl) throws SocketException omoguuje da potklase obezbede sopstvenu implementaciju UDP protokola ... ...

  • *Slanje i primanje datagramaGlavni zadatak klase DatagramSocket je da alje i prima UDP datagrame. Jedan soket moe i da alje i da prima. Zapravo, on moe slati i primati od veeg broja hostova istovremenopublic void send(DatagramPacket dp) throws IOExceptionnakon to se kreira DatagramPacket i DatagramSocket, paket se alje tako to se prosledi send() metodu soketa.Npr. ako je theSocket objekat tipa DatagramSocket i theOutput objekat tipa DatagramPacket, theOutput se alje koristei theSocket sa:theSocket.send(theOutput);Ako postoji problem sa slanjem podataka, izbacuje se IOException. Meutim to je ree sa DatagramSocket-om nego sa Socket-om ili ServerSocket-om, poto nepouzdana priroda UDP-a znai da ne elite izbacivanje izuzetka samo zato to paket nije prispeo na odredite.IOException moete dobiti ako pokuate da poaljete vei datagram nego to native mreni software hosta podrava, ali moda i ne dobijete izuzetak zbog toga. To jako zavisi od native UDP software-a OS-a i native koda izmeu ovog i Javine klase DatagramSocketImpl.Ovaj metod takoe moe izbaciti SecurityException ako nam SecurityManager ne dopusti da komuniciramo sa hostom na koji je paket adresiran. Ovo je primarno problem za aplete i drugi remotely loaded kod.

  • *Primer 3: UDP-zasnovan discard klijent.ita linije koje korisnik unosi iz System.in i alje ih discard serveru, koji prosto odbacuje sve podatke. Svaka linija se smeta u DatagramPacket. Mnogi jednostavniji Internet protokoli, poput discard, imaju i TCP i UDP implementaciju

  • *primer 3 objanjenjaklasa ima jedno statiko polje, DEFAULT_PORT, koje je postavljeno na standardni port za discard protokol (port 9) i jedan metod, main()main() metod ita hostname iz komandne linije i konvertuje taj hostname u InetAddress objekat server.BufferedReader je olanan na System.in kako bi itao ulaz korisnika sa tastatureZatim se konstruie objekat theSocket tipa DatagramSocket. Po kreiranju soketa, program ulazi u beskonanu while-petlju koja ita unos korisnika liniju po liniju koristei readLine(). Paljivi smo da koristimo iskljuivo readLine() za itanje podataka iz konzole, gde je garantovano da radi kao to bi trebalo. Poto discard protokol radi samo sa neobraenim bajtovima, moemo ignorisati probleme sa kodiranjem karaktera

  • *U while petlji, svaka linija se konvertuje u byte niz korienjem metoda getBytes() i bajtovi se smetaju u DatagramPacket theOutput. Konano, theOutput se alje preko theSocket, i petlja se nastavlja.Ako u bilo kom trenutku korisnik u liniji ukuca samo taku, program se zavrava.DatagramSocket konstruktor moe izbaciti SocketException, koji mora biti uhvaen. Poto je ovo discard klijent, ne moramo brinuti o podacima koji se vraaju od servera

  • *public void receive(DatagramPacket dp) throws IOExceptionMetod prima jedan UDP datagram sa mree i smeta ga u DatagramPacket objekat dp koji treba da postoji pre poziva metodaPoput metoda accept() klase ServerSocket, ovaj metod blokira pozivajuu nit dok datagram ne stigne. Ako Va program radi jo neto osim to eka datagrame, receive() treba pozivati u posebnoj niti

  • *Bafer datagrama treba da bude dovoljno velik za smetanje primljenih podatakaAko to nije sluaj, receive() smeta u bafer onoliko podataka koliko u njega moe da stane, ostalo se gubi.moe biti od koristi da se upamti da je maksimalna veliina dela podataka UDP datagrama 65507 bajtova (65536 = maksimalna veliina IP datagrama minus 20 bajtova = veliina IP zaglavlja, i minus 8 bajtova = veliina UDP zaglavlja). Neki application protokoli koji koriste UDP postavljaju dalja ogranienja na maksimalan broj bajtova u paketu; npr. NFS koristi pakete maksimalne veliine 8192 bajtova

  • *Ako postoji problem u primanju podataka, moe biti izbaen IOException. U praksi, to je retko.Za razliku od send(), ovaj metod ne izbacuje SecurityException ako aplet primi datagram od nekog drugog hosta. Meutim, tiho odbacuje sve takve podatke.

  • *Primer 4: UDP discard server koji prima dolazee datagrame. Samo iz zabave, loguje podatke svakog datagrama u System.out tako da moemo videti ko ta alje Vaem discard serveruklasa je jednostavna. Ima jedan metod, main(). On ita port na kome server oslukuje iz komandne linije. Ako port nije zadat u komandnoj liniji, server oslukuje na portu 9. Zatim otvara DatagramSocket na tom portu i kreira DatagramPacket sa baferom veliine 65507 bajtova dovoljno velik da primi svaki mogui paket.Server zatim ulazi u beskonanu petlju koja prima pakete i tampa sadraj i host sa koga potiu u konzoli.Discard server visokih performansi bi preskoio ovaj korakKada se datagram primi, duina paketa se postavlja na duinu podataka u tom datagramu. Iz tog razloga, u poslednjem koraku petlje, duina paketa se resetuje na maksimalnu moguu vrednost. Inae, dolazei paketi bi bili ogranieni na minimalnu veliinu svih prethodnih datagrama. Moemo pokrenuti discard klijent na jednoj maini i konektovati na discard server na drugoj maini kako bismo proverili da mrea radi

  • *public void close()Poziv metoda close() za objekat klase DatagramSocket oslobaa port koji zauzima taj soket.Npr.try{ DatagramSocket server = new DatagramSocket(); server.close();}catch(SocketException ex){ System.err.println(ex);}Nikada nije loa ideja zatvoriti DatagramSocket kada smo zavrili sa njim. Posebno je vano zatvoriti nepotreban soket ako e program nastaviti da se izvrava jo prilino dugo. Npr. u primeru 2 (UDPPortScanner) close() metod je od kljunog znaaja. Da ovaj program ne zatvara sokete koje otvara, zauzeo bi svaki UDP port sistema prilino dugo. S druge strane, ako se program zavrava uskoro nakon to zavrimo rad sa DatagramSocket-om, ne moramo eksplicitno da zatvorimo soket, soket se automatski zatvara. Zatvaranje nepotrebnih soketa je dobra programerska praksa

  • *public int getLocalPort()metod vraa int koji predstavlja lokalni port na kome soket oslukuje. Ovaj metod se koristi ako smo kreirali DatagramSocket sa anonimnim portom i elimo da saznamo koji port je pridruen soketunpr:try{ DatagramSocket ds = new DatagramSocket(); System.out.println(The socket is using port + ds.getLocalPort();}catch(SocketException ex){ ex.printStackTrace();}

  • *public InetAddress getLocalAddress() vraa InetAddress objekat koji predstavlja lokalnu adresu za koju je soket vezan. Retko je potreban u praksi. Obino ili znate ili Vas ne zanima.public SocketAddress getLocalSocketAddress() vraa SocketAddress objekat koji u sebi enkapsulira lokalni interfejs i port za koje je soket vezan

  • *Managing ConnectionsZa razliku od TCP soketa, datagram soketi nisu vrlo izbirljivi po pitanju toga sa kim komuniciraju. Zapravo, podrazumevano oni komuniciraju sa svakim, ali to esto nije ono to mi elimo. Npr. apletima je jedino doputeno da alju datagrame i primaju datagrame od svog hosta.NFS ili FSP klijent treba da prihvata pakete samo od servera sa kojim komunicirajuMrena igra treba da oslukuje datagrame samo od osoba koje igraju igruPostoji 4 metoda koji doputaju da izaberemo hostove kojima moemo da aljemo i od kojih elimo da primamo datagrame, a da odbijamo sve ostale pakete

  • *public void connect(InetAddress host, int port) ne uspostavlja zaista konekciju u TCP smislu. Meutim, odreuje da e DatagramSocket slati i primati pakete samo od zadatog udaljenog hosta na zadatom udaljenom portu. Pokuaji slanja paketa nekom drugom hostu ili portu izbacie IllegalArgumentException. Paketi primljeni od drugog hosta ili drugog porta bie odbaeni bez izuzetka ili drugog obavetenjakada se pozove connect() vri se sigurnosna provera. Ako je VM doputeno da alje podatke tom hostu i portu, provera prolazi tiho. Inae, izbacuje se SecurityException. Meutim, nakon to se napravi konekcija, send() i receive() na DatagramSocket-u ne vre vie sigurnosne provere koje uobiajeno prave

  • *public void disconnect() raskida konekciju tako da DatagramSocket moe ponovo da alje i prima pakete od bilo kog hosta i bilo kog portapublic int getPort() ako i samo ako je DatagramSocket connected, ovaj metod vraa udaljeni port na koji je konektovan. Inae, vraa -1

  • *public InetAddress getInetAddress() ako i samo ako je soket konektovan, metod vraa adresu udaljenog hosta na koji je konektovan. Inae, vraa nullpublic InetAddress getRemoteSocketAddress() isto kao i prethodnoSOCKET OPTIONS ... (page 22 of 58)

  • *SO_TIMEOUTSO_TIMEOUT je koliina vremena, u milisekundama, koju receive() eka na dolazei datagram pre nego to izbaci InterruptedIOException (potklasa od IOException). Vrednost mora biti nenegativna. Ako je 0, receive() ne istekne nikada. Ova vrednost moe se promeniti metodom setSoTimeout() i dohvatiti metodom getSoTimeout():public synchronized void setSoTimeout(int timeout) throws SocketExceptionpublic synchronized int getSoTimeout() throws IOExceptionpodrazumevano, vrednost je 0, a ima nekoliko situacija u kojima elimo da postavimo SO_TIMEOUT. Npr. ako implementiramo secure protokol koji zahteva da se odgovori dese u nekom zadatom vremenskom intervalu. Takoe, moemo odluiti da je host sa kojim komuniciramo mrtav (nedostupan ili ne odgovara) ako ne primimo odgovor pre nego to istekne odreena koliina vremenaMetod setSoTimeout() postavlja SO_TIMEOUT polje datagram soketa. Kada timeout istekne, izbacuje se InterruptedIOException.Ova opcija se postavlja pre poziva receive(). Ne moe se promeniti dok receive() eka na datagram. timeout argument mora biti vei ili jednak od 0, ako nije, setSoTimeout() izbacuje SocketExceptionNpr.

  • *try{ buffer = new byte[2056]; DatagramPacket dp = new DatagramPacket(buffer, buffer.length); DatagramSocket ds = new DatagramSocket(2048); ds.setSoTimeout(30000); // block for no more than 30 seconds try{ ds.receive(dp); // process the packet }catch(InterruptedIOException ex){ ds.close(); System.err.println(No connection within 30 seconds); }catch(SocketException ex){ System.err.println(ex); }catch(IOException ex){ System.err.println(Unexpected IOException: + ex); }}

  • *getSoTimeout() metod vraa tekuu vrednost SO_TIMEOUT polja DatagramSocket objektapublic void printSoTimeout(DatagramSocket ds){ int timeout = ds.getSoTimeout(); if(timeout > 0) System.out.println(ds + will time out after + timeout + milliseconds.); else if (timeout == 0) System.out.println(ds + will never time out.); else System.out.println(Something is seriously wrong with + ds);}

  • *Neke korisne aplikacijeNekoliko Internet servera i klijenata koji koriste DatagramPacket i DatagramSocketNeki od njih su slini sa ranijim primerima, jer mnogi Internet protokoli imaju i TCP i UDP implementacijeKada host primi IP paket, host odreuje da li je paket TCP ili UDP istraivanjem IP zaglavlja.Kao to je ranije reeno, ne postoji veza izmeu UDP i TCP portova; TCP i UDP serveri mogu deliti iste brojeve portova bez problema. Po dogovoru, ako servis ima i TCP i UDP implementaciju, koristi se isti port za obe, mada nema tehnikih razloga da to bude tako

  • *Jednostavni UDP klijentiNekoliko Internet servisa treba da zna samo adresu i port klijenta i ignorie sve podatke koje klijenti poalju u datagramimaDaytime, time i chargen su takvi protokoliSvaki od njih odgovara na neki nain, bez obzira na podatke koji su u datagramu, zapravo, bez obzira ima li bilo kakvih podataka u datagramuKlijenti za ove protokole prosto alju UDP datagram serveru i itaju odgovor koji se vrati.Poinjemo sa jednostavnim klijentom UDPPoke koji alje prazan UDP paket zadatom hostu i portu i ita odgovor od tog hosta.

  • *primer 5 - UDPPokePrimer 5 (UDPPoke): klasa UDPPoke ima 3 privatna polja: bufferSize zadaje kolika je veliina paketa koji se oekuje kao odgovor. Bafer veliine 8192 bajta je dovoljno velik za veinu protokola za koje je UDPPoke koristan, ali moe se i poveati prosleivanjem vee vrednosti konstruktoru. DatagramSocket objekat socket e se koristiti i za slanje i za primanje datagrama. Konano, DatagramPacket objekat outgoing je poruka koja se alje pojedinanim serverima

  • *Konstruktori inicijalizuju sva 3 polja koristei InetAddress za host i int-ove za port, duinu bafera i broj milisekundi koliko se eka. Ova poslednja 3 postaju deo DatagramSocket polja socket. Ako duina bafera nije zadata, koristi se 8192. Ako timeout nije zadat, 30 sekundi (30000 milisekundi) se koristi. Host, port i veliina bafera se takoe koriste za konstruisanje outgoing DatagramPacket-a.Iako bi teoretski trebalo da bude mogue poslati datagram bez podataka, bug-ovi u nekim Java implementacijama zahtevaju da dodamo bar jedan bajt podataka datagramu.Jednostavni serveri koje trenutno razmatramo ignoriu ove podatke

  • *poke() metodNakon to je UDPPoke objekat konstruisan, klijenti pozivaju njegov poke() metod da poalju prazan outgoing datagram odreditu i proitaju odgovorodgovor se inicijalno postavlja na nullkada se oekivani datagram pojavi, njegovi podaci se kopiraju u polje responsemetod vraa null ako odgovor ne doe dovoljno brzo ili ne doe uopte

  • *main()main() metod prosto ita host i port na koje se treba konektovati iz komandne linije, konstruie UDPPoke objekat i poziva poke() metod.Veina jednostavnih protokola kojima odgovara ovaj klijent vraa ASCII tekst, tako da pokuavamo da konvertujemo odgovor u ASCII string i tampamo ga.Ne podravaju sve VM ASCII kodiranje karaktera, pa obezbeujemo mogunost korienja ASCII nadskupa Latin-1 (8859-1) kao backup

  • *kada imamo klasu UDPPoke, UDP daytime, time, chargen i quote of the day klijenti su skoro trivijalni.Primer 6: time clientnajkomplikovaniji deo je konvertovanje 4 neobraena bajta koja je vratio server u java.util.Date objekat. Korien je isti algoritam kao za TCP verziju klijentaostali protokoli se ostavljaju za vebu

  • *UDP ServerKlijenti nisu jedini programi koji dobijaju benefit od reusable implementacije. Serveri za ove protokole su veoma slini.Svi oni ekaju UDP datagrame na zadatom portu i odgovarju na svaki datagram drugim datagramom.Serveri se razlikuju samo po sadraju datagrama koje vraaju

  • *primer 7: UDPServerjednostavna klasa koja se moe naslediti da obezbedi specifine servere za razliite protokoleUDPServer klasa ima dva polja: int bufferSize i DatagramSocket socket, od kojih je drugo protected pa ga potklase mogu koristitiKonstruktor otvara DatagramSocket socket na zadatom lokalnom portu kako bi primao datagrame ne vee od bufferSize bajtovaUDPServer nasleuje Thread tako da se vei broj instanci moe paralelno izvravati. Njegov run() metod sadri beskonanu petlju koja uzastopno prima dolazei datagram i odgovara prosleujui ga apstraktnom respond() metodu. Ovaj metod e biti predefinisan odgovarajuim potklasama u cilju implementiranja razliitih vrsta serveraUDPServer je veoma fleksibilna klasa. Potklase mogu poslati 0, 1 ili mnogo datagrama kako bi odgovorile na svaki datagram koji doe.Ako je neophodno dosta procesiranja kako bi se odgovorilo na paket, respond() metod se moe poslati u nit kako bi odradio to. Meutim, UDP serveri tee da nemaju produene interakcije sa klijentom. Svaki paket koji doe tretira se nezavisno od ostalih paketa, tako da se odgovorom obino rukuje direktno u metodu respond(), bez generisanja niti.

  • *primer 8: FastUDPDiscardServerNajlaki protokol za obradu je discardsve to treba napisati je main() metod koji postavlja port i startuje nit.respond() je metod koji ne radi nitaprimer je UDP discard server visokih performansi koji ne radi nita sa dolazeim paketima

  • *primer 9: LoggingUDPDiscardServerza nijansu interesantniji discard server koji tampa dolazee pakete u System.out

    primer 10: UDPEchoServer

    Nije mnogo tee implementirati echo server. Za razliku od stream-based TCP echo servera, ovde nije potreban vei broj niti da bi se rukovalo veim brojem klijenata

    primer 11: UDPDaytimeServer

    samo neznatno komplikovaniji. Server oslukuje UDP datagrame na portu 13. Kada detektuje dolazei datagram, vraa tekui datum i vreme na serveru kao jednoredni ASCII string.

  • *primer 12: UDP Echo Clientklasa UDPPoke implementirana ranije nije pogodna za sve protokole. Posebno, protokoli koji zahtevaju vei broj datagrama zahtevaju drugaiju implementacijuEcho protokol ima i TCP i UDP implementacijuImplementiranje echo protokola TCP-jem je jednostavno. Sa UDP-om je komplikovanije jer nemamo I/O tokove niti koncept konekcijeTCP zasnovan echo klijent moe poslati poruku i ekati na odgovor na istoj konekciji. Meutim, UDP zasnovan echo klijent nema garancije da je poruka koju je poslao primljena. Zato ne moe prosto ekati na odgovor, mora biti spreman da alje i prima podatke asinhrono

  • *Korienjem niti ovo ponaanje je prilino jednostavno za implementaciju.Jedna nit moe da procesira ulaz korisnika i alje ga echo serveru, dok druga nit prihvata ulaz od servera i prikazuje ga korisniku.Klijent je podeljen u 3 klase: glavnu UDPEchoClient, SenderThread klasu i ReceiverThread klasu

  • *UDPEchoClient klasa treba da izgleda poznato. ita hostname iz komandne linije i konvertuje ga u InetAddress objekat.UDPEchoClient koristi ovaj objekat i podrazumevani echo port da konstruie SenderThread objekat. Konstruktor moe izbaciti SocketException, pa se on hvata. Zatim startuje SenderThread. Isti DatagramSocket koji koristi SenderThread koristi se za konstruisanje ReceiverThread, koja se zatim startuje.Vano je koristiti isti DatagramSocket i za primanje i za slanje podataka jer e echo server poslati odgovor nazad na port sa koga su podaci poslati

  • *klasa SenderThreadSenderThread klasa ita ulaz iz konzole, liniju po liniju, i alje to echo serveru.ulaz se obezbeuje sa System.in, ali drugaiji klijent bi mogao da ukljui opciju itanja iz drugog toka moda otvaranjem FileInputStream da ita iz fajla.3 polja ove klase definiu server kome se alju podaci, port na tom serveru i DatagramSocket koji vri slanje, sve se postavlja u jednom konstruktoruDatagramSocket je konektovan na udaljeni server kako bi se osigurao da su svi primljeni datagrami zapravo poslati od strane pravog servera. Prilino je neverovatno da e neki drugi server sa Interneta bombardovati ovaj port udnim podacima. Meutim, dobra je navika osigurati da paketi koje primamo dolaze sa pravog mesta, posebno ako je sigurnost bitna

  • *metod run() procesira ulaz liniju po liniju.Da bi ovo uradio, BufferedReader userInput je olanan na System.in.beskonana petlja ita linije korisnikovog ulaza.svaka linija se smeta u theLine.sama taka u liniji oznaava kraj ulaza korisnika i prekida petljuinae, bajtovi podataka se smetaju u niz korienjem getBytes() metoda klase java.lang.String.Dalje, niz se smeta u koristan deo DatagramPacket-a output, zajedno sa informacijom o serveru, portu i duinom podataka.Ovaj paket se alje svom odreditu korienju socket-a.Ova nit zatim radi yield da da ansu drugim nitima da se izvravaju

  • *klasa ReceiverThreadReceiverThread klasa eka da stignu datagrami iz mree.Kada se datagram primi, konvertuje se u String i tampa na System.out kako bi se prikazao korisniku. Napredniji EchoClient moe ukljuiti opciju slanja izlaza negde drugdeKlasa ima 2 polja. Vanije je DatagramSocket theSocket, koje mora biti isti DatagramSocket koji koristi SenderThread. Podaci stiu na port koji koristi taj DatagramSocket. Bilo kom drugom DatagramSocket-u ne bi bilo doputeno da se konektuje na isti port. Drugo polje, stopped, je boolean koji se koristi da prekine ovu nit bez poziva stop() metoda

  • *run() metod je beskonana petlja koja koristi receive() metod socket-a da eka na dolazee datagramekada se pojavi dolazei datagram, konvertuje se u String iste duine kao to su dolazei podaci i tampa na System.out.Kao i ulazna nit, ova nit zatim radi yield kako bi dala ansu i drugim nitima da se izvravaju

  • *DatagramChannelKlasa se koristi u neblokirajuim UDP aplikacijamaMoe biti registrovana Selector-om. To je korisno u serverima gde jedna nit moe obraivati komunikaciju sa vie razliitih klijenata. Meutim, UDP je po svojoj prirodi mnogo vie asinhron nego TCP, pa je efekat manji

  • U UDP je uvek sluaj da jedan datagram soket moe procesirati zahteve veeg broja klijenata i za ulazom i za izlazomDatagramChannel klasa dodaje mogunost da se to ini na neblokirajui nain, pa metodi vraaju kontrolu brzo ako mrea nije momentalno spremna da primi ili poalje podatke*

  • Korienje DatagramChannelKoristi se i klasa DatagramSocket kako bi se kanal vezao za port. Meutim, kasnije se vie ne mora koristiti, kao ni DatagramPacket, koja se ne koristi uopte.itaju se i piu ByteBuffer objekti, kao sa SocketChannel.*

  • Otvaranje soketaKlasa ne poseduje javne konstruktoreNovi DatagramChannel objekat se kreira korienjem statikog open() metoda:public static DatagramChannel open() throws IOExceptionNpr.DatagramChannel channel = DatagramChannel.open();*

  • Kanal inicijalno nije vezan ni za jedan portDa bismo ga vezali, treba da pristupimo kanalovom peer objektu tipa DatagramSocket, koristei metod socket():public abstract DatagramSocket socket()Npr. da veemo channel za port 3141:SocketAddress address=new InetSocketAddress(3141);DatagramSocket socket = channel.socket();socket.bind(address);

    *

  • Povezivanje (konektovanje)Poput DatagramSocket, i DatagramChannel moe biti konektovan, tj. moe biti konfigurisan tako da prima datagrame od i alje datagrame iskljuivo jednom hostu. To se postie metodompublic abstract DatagramChannel connect(SocketAddress remote) throws IOException*

  • Ipak, za razliku od connect() metoda klase SocketChannel, ovaj metod zapravo ne alje niti prima pakete preko mree, jer je UDP connectionless protokol.Zato ovaj metod brzo vraa kontrolu, ne blokira.Postoji isConnected() metod koji vraa true akko je DatagramSocket konektovan:public abstract boolean isConnected()(kae da li je DatagramChannel ogranien na 1 hosta)*

  • Za razliku od SocketChannel, DatagramChannel ne mora da bude konektovan da bi slao ili primao podatkedisconnect() metod raskida konekciju:public abstract DatagramChannel disconnect() throws IOException doputa da kanal ponovo moe da alje i prima podatke od veeg broja hostova*

  • Konektovani kanali mogu biti bri od nekonektovanih kod apleta jer VM mora da proveri da li je konekcija doputena samo prilikom inicijalnog poziva connect() metoda, a ne svaki put kada se primi ili poalje paket.*

  • Primanje (receiving)Metod receive() ita 1 datagram paket iz kanala u ByteBuffer. Vraa adresu hosta koji je poslao paket: public abstract SocketAddress receive(ByteBuffer dst) throws IOExceptionAko je kanal blokirajui (podrazumevano), metod nee vratiti kontrolu dok ne proita paketAko je kanal neblokirajui, metod neposredno vraa null ako paket nije dostupan za itanje*

  • Ako datagram paket sadri vie podataka nego to moe da stane u bafer, viak podataka se odbacuje bez obavetenja o problemu. Ne dobijamo BufferOverflowException niti bilo ta slino. Na kraju krajeva, UDP je nepouzdan.Ovakvo ponaanje uvodi novi nivo nepouzdanosti. Podaci mogu bezbedno prispeti iz mree i izgubljeni u naem sopstvenom programu*

  • Primer: discard serverKoristei metod receive() ponovo implementiramo discard server koji loguje host koji je poslao podatke, kao i same podatkePrimer izbegava potencijalni gubitak podataka koristei bafer koji je dovoljno velik da sadri UDP paket i istei ga pre ponovne upotrebe*

  • Slanje (sending)Metod send() pie 1 datagram paket iz ByteBuffer u kanal za adresu zadatu kao drugi argument: public abstract int send(ByteBuffer src, SocketAddress target) throws IOExceptionIzvor ByteBuffer moe biti ponovo iskorien ako elimo da iste podatke poaljemo veem broju klijenata. Samo ne smemo da zaboravimo da ga najpre premotamo (rewind)*

  • Metod send() vraa broj ispisanih bajtovaTo e biti ili broj bajtova preostalih u izlaznom baferu ili 00 je ako nema dovoljno prostora u izlaznom baferu mrenog interfejsa za koliinu podataka koju pokuamo da poaljemoAko stavimo vie podataka u bafer nego to mreni interfejs moe da prihvati, on nikada nita nee poslati. Ovaj metod ne deli podatke u vei broj paketa. On pie sve ili nita.*

  • Primer: jednostavan echo server zasnovan na kanalimaMetod receive() ita paket, uglavnom kao i u prethodnom primeru. Meutim, sada, radije nego da loguje paket na System.out, vraa iste podatke klijentu koji ih je poslaoOvaj program je blokirajui i sinhron. To je mnogo manji problem za UDP-protokole nego za TCP. Server ne mora i ne eka da klijent bude spreman da primi podatke*

  • ReadingOsim metoda receive() specijalne namene, DatagramChannel ima i uobiajena 3 read() metoda (prvi prima jedan argument tipa ByteBuffer, drugi jedan argument tipa ByteBuffer[], a trei tri argumenta: prvi tipa ByteBuffer[], a zatim i dva int-a: offset i lengthOvi metodi se mogu koristiti samo na konektovanim kanalima, tj. pre poziva nekog od ovih metoda mora se pozvati connect() da zalepi kanal za odreeni udaljeni host*

  • Ovo ih ini pogodnijim za korienje od strane klijenata koji znaju sa kim e komunicirati, nego za servere koji moraju prihvatati ulaz od mnogih hostova istovremeno, a koji normalno nisu poznati pre pristizanja prvog paketa od njihSvaki od ova 3 read() metoda ita 1 datagram paket iz mree. to je mogue vie podataka iz tog datagrama smeta se u argument ByteBuffer(s).Svaki read() metod vraa broj proitanih bajtova ili -1 ako je kanal zatvoren. Moe vratiti 0 iz jednog od sledeih razloga: - kanal je neblokirajui i nema spremnih paketa - datagram paket ne sadri podatke - bafer je pun*

  • Kao i sa receive() metodom, ako datagram paket ima vie podataka nego to ByteBuffer(s) moe da sadri, viak podataka se odbacuje bez informacije o problemu*

  • WritingDatagramChannel ima 3 write() metoda koja se mogu koristiti umesto metoda send()Prvi prima 1 argument tipa ByteBuffer, drugi 1 argument tipa ByteBuffer[], a trei tri argumenta: prvi tipa ByteBuffer[], a zatim dva int-a: offset i lengthOvi metodi mogu biti korieni samo sa konektovanim kanalima, inae ne znaju gde da poalju paket*

  • Svaki od ovih metoda alje 1 datagram paket preko konekcije. Nijedan od njih ne garantuje da e ispisati kompletan sadraj bafera. Meutim kursor-zasnovana priroda bafera nam omoguuje da zovemo ovaj metod iznova i iznova sve dok se bafer potpuno ne isprazni i podaci svi poalju, moda koristei vei broj datagram paketa:while(buffer.hasRemaining() && channel.write(buffer)!=-1);*

  • Primer: UDP echo klijentMoemo koristiti read() i write() metode da implementiramo jednostavni UDP echo klijentNa klijentskoj strani, jednostavno je izvriti konektovanje pre slanja. Poto paketi mogu biti izgubljeni prilikom slanja (zapamtiti uvek da je UDP nepouzdan), ne elimo da odlaemo slanje dok ekamo da primimo paketZato moemo da iskoristimo prednost selektora i neblokirajueg I/O. Oni funkcioniu za UDP isto kao i za TCP. Ovog puta, meutim, umesto slanja tekstualnih podataka, poaljimo 100 int-ova od 0 do 99. tampaemo vraene vrednosti tako da je jednostavno otkriti ako je neki paket izgubljen.*

  • Postoji 1 kljuna razlika izmeu selektovanja TCP kanala i selektovanja datagram kanala. Poto su datagram kanali isto connectionless (uprkos connect() metodu), moramo da primetimo kada je transfer podataka gotov i da zavrimo. U ovom primeru, pretpostavljamo da su podaci gotovi kada su svi paketi poslati i 1 minut je proao otkako je poslednji paket primljen. Svi oekivani paketi koji nisu pristigli do tog momenta smatraju se izgubljenim*

  • ZatvaranjeKao i sa regularnim datagram soketima, kanal treba zatvoriti kada smo zavrili sa njim kako bi se oslobodio port, i drugi, eventualno korieni, resursi public void close() throws IOExceptionZatvaranje ve zatvorenog kanala nema efektaPokuaj pisanja podataka ili itanja podataka iz zatvorenog kanala izbacuje izuzetak public boolean isOpen()*

    ***