Programovanie

Tip Java 18: Implementácia funkcie časového limitu pre JDK 1.0.2 DatagramSocket

Ak ste vyvinuli aplikáciu Java, ktorá používa zásuvku Datagram na odosielanie a prijímanie správ, možno ste sa stretli s potrebou implementovať funkciu časového limitu na odblokovanie DatagramSocket prijímacia metóda. Bez funkcie časového limitu by sa vaša aplikácia blokovala, kým nedostane správu, a pretože doručenie Datagramu nie je zaručené, mohla by sa blokovať naozaj dlho. Tento tip v jazyku Java popíše techniku ​​pre časový limit a odblokovanie DatagramSocket prijímacia metóda.

Pravdepodobne ste už uhádli, že táto technika využíva vlákna. Programovanie závitov v Jave je celkom príjemné. Dalo by sa to porovnať s radosťami z lyžovania pri jazere Tahoe alebo z plavby blízko pobrežia Santa Cruz. (Dobre, možno to tak nie je že príjemné, ale stále je to veľká zábava!)

Keď uvažujete o metóde na dosiahnutie funkcie časového limitu, asi prvou a najočividnejšou schémou, ktorá mi príde na myseľ, je umiestniť funkcionalitu príjmu DatagramSocket do samostatného vlákna a potom spustiť ešte ďalšie vlákno ako časovač, ktorý by po uplynutí platnosti zabil príjem. vlákno, ak je ešte nažive. Aj keď táto metóda bude fungovať, pravdepodobne to nie je najgrádnejší spôsob, ako úlohu splniť.

Namiesto zabitia vlákna, ktoré je blokované pri metóde prijímania, som chcel elegantnejšie riešenie - také, ktoré by odblokovalo metódu prijímania. Aby som to dosiahol, potreboval som vlákno, ktoré bolo schopné odoslať správu datagramu do prijímacieho vlákna, aby som odblokoval prijímajúce vlákno po uplynutí časového limitu. Vlákno časového limitu je implementované ako jeho vlastná trieda a prijímajúce vlákno vytvorí inštanciu triedy časového limitu tesne pred blokovaním na metóde príjmu. Nasledujúci kód zobrazuje implementáciu triedy časového limitu. Upozorňujeme, že z dôvodu stručnosti je spracovanie výnimiek vynechané.

import java.io. *; import java.net. *; import java.lang. *; verejná trieda DatagramWatchdogTimer implementuje Runnable {DatagramWatchdogTimer (int timeoutSeconds) hodí SocketException {timeout = timeoutSeconds; socket = nový DatagramSocket (); datagramPort = socket.getLocalPort (); Thread thisThread = nové vlákno (toto); thisThread.start (); } public int getPort () {return datagramPort; } public void run () {// vytvoriť štandardnú správu s odpoveďou, ktorá označuje // správa pochádza z DatagramWatchdogTimer //, v mojom prípade stačí nula. Reťazec responseStr = nové celé číslo (0) .toString (); byte [] responseBuf = nový bajt [replyStr.length ()]; responseStr.getBytes (0, replyStr.length (), replyBuff, 0); int replyLength = replyStr.length (); // prijme správu z prijímacieho vlákna. // je to nevyhnutné, aby sme vedeli, ako na ňu poslať odblokovaciu // správu. byte [] buffer = new bute [128]; Paket DatagramPacket = nový DatagramPacket (buffer, buffer.length); socket.receive (paket); // vyprší časový limit sekúnd a potom pošle odblokovaciu // správu späť. Thread.sleep (časový limit * 1 000); int requestorPort = packet.getPort (); InetAddress requestorAddress = packet.getAddress (); DatagramPacket sendPacket = nový DatagramPacket (replyBuff, responseLength, requestorAddress, requestorPort); DatagramSocket sendSocket = nový DatagramSocket (); sendSocket.send (sendPacket); } časový limit súkromného int; private int datagramPort; súkromná zásuvka DatagramSocket; } 

Ako už bolo spomenuté vyššie, kedykoľvek vaša aplikácia potrebuje prijať správu datagramu, môže vytvoriť inštanciu súboru DatagramWatchdogTimer triedy na nastavenie časového limitu. Ak aplikácia nedostane skutočnú správu v časovom limite niekoľkých sekúnd, odblokuje sa prijatím správy o odblokovaní z aplikácie DatagramWatchdogTimer trieda.

Tu je príklad:

// aplikačný kód int timeoutSeconds = 5; InetAddress myAddress = InetAddress.getByName (""); // vytvorenie inštancie triedy časovačov DatagramWatchdogTimer wdTimer = nový DatagramWatchdogTimer (timeoutSeconds); int wdPort = wdTimer.getPort (); // pošlite správu wdTimer na spustenie časovača // msgBuff môže byť čo chcete. String msgString = new String ("time me"); byte [] msgBuff = nový bajt [msgString.length ()]; msgString.getBytes (0, msgString.length (), msgBuff, 0); DatagramSocket socket = nový DatagramSocket (); DatagramPacket wdPacket = nový DatagramPacket (msgBuff, msgLength, myAddress, wdPort); socket.send (wdPacket); // teraz môžete čítať zo soketu a máte istotu //, že ho zablokujete iba na timeoutSeconds. byte [] buffer = nový bajt [1024]; Paket DatagramPacket = nový DatagramPacket (buffer, buffer.length); socket.receive (paket); if (myAddress.equals (packet.getAddress) == true) {// prijatá správa od objektu časovača} else {// prijatá skutočná správa} 

Pri použití tejto techniky nezabudnite použiť rovnaký DatagramSocket na odosielanie do objektu DatagramWatchdogTimer aj na príjem datagramov. To zaisťuje, že objekt DatagramWatchdogTimer vie, kam má odoslať správu o odblokovaní. Vo vyššie uvedenom ukážkovom kóde sa tiež použil dynamicky pridelený port vytvorením inštancie DatagramSocket () bez akýchkoľvek argumentov. Fungovalo by to aj pomocou známeho portu podľa vášho výberu, napríklad DatagramSocket (8000). Nakoniec môžete chcieť, aby objekt časovača poslal viac ako jednu odblokovaciu správu - len aby ste zvýšili pravdepodobnosť, že ju aplikácia prijme. To by nemal byť problém, pretože objekt časovača beží ako vlákno na rovnakom stroji ako aplikácia.

Albert Lopez bol členom technického personálu spoločnosti Sun Microsystems od roku 1989 do roku 1995. Nedávno prešiel do tímu informačných systémov v Chicagskej obchodnej rade, kde je vedúcim členom vývojového tímu Java, ktorý vyvíja novú generáciu. elektronický obchodný systém využívajúci Javu.

Tento príbeh, „Java Tip 18: Implementácia funkcie časového limitu pre JDK 1.0.2 DatagramSocket“, bol pôvodne publikovaný spoločnosťou JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found