Programování

Tip Java 18: Implementace funkce časového limitu pro JDK 1.0.2 DatagramSocket

Pokud jste vyvinuli aplikaci Java, která používá zásuvku Datagram k odesílání a přijímání zpráv, možná jste narazili na potřebu implementovat funkci časového limitu pro odblokování DatagramSocket přijímací metoda. Bez funkce časového limitu by se vaše aplikace blokovala, dokud neobdrží zprávu, a protože doručení datagramu není zaručeno, mohla by se vaše aplikace blokovat opravdu dlouho. Tento tip Java popisuje techniku ​​pro vypršení časového limitu a odblokování DatagramSocket přijímací metoda.

Pravděpodobně jste již uhodli, že tato technika bude využívat vlákna. Programování vláken v Javě je docela příjemné. Dalo by se to srovnat s radostmi z lyžování u jezera Tahoe nebo z plavby poblíž pobřeží Santa Cruz. (Dobře, možná to tak není.) že příjemné, ale stále je to spousta legrace!)

Když uvažujete o metodě k dosažení funkce časového limitu, možná první a nejzřejmější schéma, které mě napadne, je umístit funkci příjmu DatagramSocket do samostatného vlákna a poté spustit další vlákno jako časovač, který by po vypršení platnosti zabil příjem vlákno, pokud je stále naživu. I když tato metoda bude fungovat, pravděpodobně nejde o nejpůvabnější způsob, jak úkol splnit.

Místo toho, abych zabil vlákno, které je blokováno na metodě příjmu, chtěl jsem elegantnější řešení - takové, které by odblokovalo metodu příjmu. K dosažení tohoto cíle jsem potřeboval vlákno, které bylo schopné odeslat zprávu datagramu do přijímajícího vlákna, aby se odblokovalo přijímající vlákno po uplynutí časového limitu. Vlákno časového limitu je implementováno jako jeho vlastní třída a přijímající vlákno vytvoří instanci třídy časového limitu těsně před blokováním v metodě příjmu. Následující kód ukazuje implementaci třídy časového limitu. Všimněte si, že pro stručnost je zpracování výjimek vynecháno.

importovat java.io. *; importovat java.net. *; import java.lang. *; veřejná třída DatagramWatchdogTimer implementuje Runnable {DatagramWatchdogTimer (int timeoutSeconds) hodí SocketException {timeout = timeoutSeconds; socket = new DatagramSocket (); datagramPort = socket.getLocalPort (); Thread thisThread = nové vlákno (toto); thisThread.start (); } public int getPort () {return datagramPort; } public void run () {// vytvořit standardní odpověď, která označuje // zpráva pochází z DatagramWatchdogTimer // v mém případě stačí nula. Řetězec responseStr = new Integer (0) .toString (); byte [] responseBuf = nový bajt [replyStr.length ()]; replyStr.getBytes (0, replyStr.length (), replyBuff, 0); int replyLength = replyStr.length (); // přijme zprávu z přijímajícího vlákna. // to je nutné, abychom věděli, jak na něj odeslat odblokovací // zprávu. byte [] buffer = new bute [128]; Paket DatagramPacket = nový DatagramPacket (buffer, buffer.length); socket.receive (paket); // počkejte časový limit v sekundách a poté odešlete odblokovací // zprávu zpět. Thread.sleep (časový limit * 1000); 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 soukromého int; private int datagramPort; soukromá zásuvka DatagramSocket; } 

Jak bylo uvedeno výše, kdykoli vaše aplikace potřebuje přijmout zprávu datagramu, může vytvořit instanci DatagramWatchdogTimer třídy pro nastavení časového limitu. Pokud aplikace neobdrží skutečnou zprávu do timeout sekund, odblokuje se přijetím odblokovací zprávy z DatagramWatchdogTimer třída.

Zde je příklad:

// kód aplikace int timeoutSeconds = 5; InetAddress myAddress = InetAddress.getByName (""); // vytvoření instance třídy časovače DatagramWatchdogTimer wdTimer = nový DatagramWatchdogTimer (timeoutSeconds); int wdPort = wdTimer.getPort (); // pošlete zprávu wdTimer pro spuštění časovače // msgBuff může být cokoli 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); // nyní můžete číst ze zásuvky a mít jistotu //, že ji zablokujete pouze na timeoutSeconds. byte [] buffer = nový bajt [1024]; Paket DatagramPacket = nový DatagramPacket (buffer, buffer.length); socket.receive (paket); if (myAddress.equals (packet.getAddress) == true) {// přijatá zpráva od objektu časovače} else {// přijata skutečná zpráva} 

Při použití této techniky nezapomeňte použít stejný DatagramSocket pro odesílání do objektu DatagramWatchdogTimer i pro příjem datagramů. Tím je zajištěno, že objekt DatagramWatchdogTimer ví, kam má poslat zprávu o odblokování. Také v ukázkovém kódu zobrazeném výše byl použit dynamicky přidělený port vytvořením instance DatagramSocket () bez jakýchkoli argumentů. Fungovalo by to také pomocí známého portu podle vašeho výběru, jako je DatagramSocket (8000). Nakonec můžete chtít, aby objekt časovače odeslal více než jednu odblokovací zprávu - jen abyste zvýšili šance, že aplikace ji přijme. To by neměl být problém, protože objekt časovače běží jako podproces na stejném počítači jako aplikace.

Albert Lopez byl členem technického týmu Sun Microsystems od roku 1989 do roku 1995. Nedávno se stal členem týmu Information Systems v Chicagské obchodní radě, kde je vedoucím členem vývojového týmu Java, který vyvíjí novou generaci elektronický obchodní systém využívající Javu.

Tento příběh, „Java Tip 18: Implementace funkce časového limitu pro JDK 1.0.2 DatagramSocket“, původně publikoval JavaWorld.

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