Java savjet 18: Implementacija značajke vremenskog ograničenja za JDK 1.0.2 DatagramSocket

Ako ste razvili Java program koji koristi Datagram utičnicu za slanje i primanje poruka, tada ste možda naišli na potrebu za implementacijom značajke vremenskog ograničenja za deblokiranje DatagramSocketmetode primanja. Bez značajke vremenskog ograničenja aplikacija bi se blokirala dok ne primi poruku, a budući da isporuka Datagrama nije zajamčena, aplikacija bi mogla blokirati jako dugo. Ovaj će Java savjet opisati tehniku ​​za vremensko ograničenje i deblokadu DatagramSocketmetode primanja.

Vjerojatno ste već pogodili da će se u ovoj tehnici koristiti niti. Programiranje niti u Javi prilično je ugodno. To bi se moglo usporediti s radostima skijanja na jezeru Tahoe ili plovidbe u blizini obale Santa Cruza. (OK, možda nije toliko ugodno, ali svejedno je jako zabavno!)

Kada razmišljate o metodi za postizanje značajke vremenskog ograničenja, možda je prva i najočitija shema koja vam pada na pamet smjestiti funkciju primanja DatagramSocket-a u zasebnu nit, a zatim pokrenuti još jednu nit kao tajmer koji bi, po isteku, ubio primanje konac ako je još živ. Iako će ova metoda funkcionirati, vjerojatno nije najljepši način za izvršenje zadatka.

Umjesto da ubijem nit koja je blokirana na metodi primanja, želio sam elegantnije rješenje - ono koje će deblokirati metodu primanja. Da bih to postigao, trebala mi je nit koja je sposobna poslati poruku datagrama primajućoj niti da bi deblokirala primajuću nit nakon isteka vremenskog ograničenja. Nit vremenskog ograničenja implementiran je kao vlastita klasa, a primajuća nit stvara primjerak klase vremenskog ograničenja neposredno prije blokiranja metode primanja. Sljedeći kod prikazuje implementaciju klase vremenskog ograničenja. Imajte na umu da je za kratkoću izostavljeno rukovanje iznimkama.

import java.io. *; import java.net. *; import java.lang. *; javna klasa DatagramWatchdogTimer implementira Runnable {DatagramWatchdogTimer (int timeoutSeconds) baca SocketException {timeout = timeoutSeconds; socket = novi DatagramSocket (); datagramPort = socket.getLocalPort (); Thread thisThread = nova nit (ovo); thisThread.start (); } javni int getPort () {return datagramPort; } public void run () {// stvoriti standardnu ​​poruku odgovora koja ukazuje // poruka je došla iz DatagramWatchdogTimer // u mom slučaju dovoljna je nula. String replyStr = novi cijeli broj (0) .toString (); bajt [] replyBuf = novi bajt [replyStr.length ()]; replyStr.getBytes (0, replyStr.length (), replyBuff, 0); int replyLength = replyStr.length (); // primanje poruke iz primajuće niti. // to je neophodno kako bismo znali kako poslati // poruku za deblokiranje natrag.bajt [] me uspremnik = novo bute [128]; DatagramPacket paket = novi DatagramPacket (međuspremnik, buffer.length); socket.receive (paket); // pričekajte timeout broj sekundi, a zatim vratite // poruku za deblokiranje. Thread.sleep (timeout * 1000); int requeststorPort = packet.getPort (); InetAddress requeststorAddress = packet.getAddress (); DatagramPacket sendPacket = novi DatagramPacket (replyBuff, replyLength, requeststorAddress, requeststorPort); DatagramSocket sendSocket = novi DatagramSocket (); sendSocket.send (sendPacket); } privatno int timeout; privatni int datagramPort; privatna utičnica DatagramSocket; }getPort (); InetAddress requeststorAddress = packet.getAddress (); DatagramPacket sendPacket = novi DatagramPacket (replyBuff, replyLength, requeststorAddress, requeststorPort); DatagramSocket sendSocket = novi DatagramSocket (); sendSocket.send (sendPacket); } privatno int timeout; privatni int datagramPort; privatna utičnica DatagramSocket; }getPort (); InetAddress requeststorAddress = packet.getAddress (); DatagramPacket sendPacket = novi DatagramPacket (replyBuff, replyLength, requeststorAddress, requeststorPort); DatagramSocket sendSocket = novi DatagramSocket (); sendSocket.send (sendPacket); } privatno int timeout; privatni int datagramPort; privatna utičnica DatagramSocket; }

Kao što je gore spomenuto, kad god vaša aplikacija treba primiti poruku datagrama, može stvoriti instancu DatagramWatchdogTimerklase za postavljanje vremenskog ograničenja. Ako aplikacija u roku od nekoliko sekundi ne primi stvarnu poruku, deblokirat će se primanjem poruke o deblokiranju iz DatagramWatchdogTimerrazreda.

Evo primjera:

// kod aplikacije int timeoutSeconds = 5; InetAddress myAddress = InetAddress.getByName (""); // stvorimo instancu klase timera DatagramWatchdogTimer wdTimer = novi DatagramWatchdogTimer (timeoutSeconds); int wdPort = wdTimer.getPort (); // pošalji poruku na wdTimer za pokretanje odbrojavanja // msgBuff može biti što god želite. String msgString = new String ("vrijeme me"); bajt [] msgBuff = novi bajt [msgString.length ()]; msgString.getBytes (0, msgString.length (), msgBuff, 0); DatagramSocket socket = novi DatagramSocket (); DatagramPacket wdPacket = novi DatagramPacket (msgBuff, msgLength, myAddress, wdPort); socket.send (wdPacket); // sada možete čitati iz utičnice i imati neka uvjerenja // da ćete blokirati samo timeoutSeconds. bajt [] međuspremnik = novi bajt [1024]; DatagramPacket paket = novi DatagramPacket (međuspremnik,pufer.duljina); socket.receive (paket); if (myAddress.equals (packet.getAddress) == true) {// primljena poruka od objekta timera} else {// primljena stvarna poruka}

Kada koristite ovu tehniku, obavezno koristite isti DatagramSocket i za slanje na objekt DatagramWatchdogTimer i za primanje datagrama. To osigurava da objekt DatagramWatchdogTimer zna kamo poslati poruku o deblokiranju. Također, u primjeru koda prikazanom gore korišten je dinamički dodijeljeni port instancijom DatagramSocket () bez ikakvih argumenata. Također bi radio pomoću dobro poznatog priključka po vašem izboru, poput DatagramSocket (8000). Konačno, možda ćete htjeti da objekt odbrojavanja pošalje više od jedne poruke za deblokiranje - samo da biste povećali šanse da ga aplikacija primi. To ne bi trebao predstavljati problem jer se objekt odbrojavanja izvodi kao nit na istom stroju kao i aplikacija.

Albert Lopez bio je član tehničkog osoblja u Sun Microsystems od 1989. do 1995. Nedavno se pridružio osoblju za informacijske sustave u čikaškom Odboru za trgovinu, gdje je vodeći član Java razvojnog tima koji razvija sljedeću generaciju sustav elektroničkog trgovanja pomoću Jave.

Ovu priču, "Java tip 18: Implementacija značajke vremenskog ograničenja za JDK 1.0.2 DatagramSocket" izvorno je objavio JavaWorld.