Ohjelmointi

Java Tip 18: Aikakatkaisutoiminnon käyttöönotto JDK 1.0.2 DatagramSocketille

Jos olet kehittänyt Java-sovelluksen, joka käyttää Datagram-liitäntää viestien lähettämiseen ja vastaanottamiseen, saatat joutua kohtaamaan aikakatkaisutoiminnon tarpeen poistaa DatagramSocket vastaanoton menetelmä. Ilman aikakatkaisuominaisuutta sovelluksesi estetään, kunnes se saa viestin, ja koska Datagram-toimitusta ei taata, sovelluksesi voi estää todella pitkään. Tämä Java-vinkki kuvaa tekniikkaa, jolla ajoitetaan ja estetään DatagramSocket vastaanoton menetelmä.

Olet todennäköisesti jo arvannut, että tässä tekniikassa hyödynnetään ketjuja. Langan ohjelmointi Java: ssa on varsin nautinnollista. Voisi verrata sitä Tahoe-järven hiihtämisen tai Santa Cruzin rannikon lähellä purjehtimisen iloihin. (OK, ehkä se ei ole että nautittavaa, mutta se on silti hauskaa!)

Kun ajatellaan aikakatkaisutoiminnon toteuttamismenetelmää, ehkä ensimmäinen ja ilmeisin mieleen tuleva järjestelmä on sijoittaa DatagramSocket-vastaanottotoiminnot erilliseen säikeeseen ja käynnistää sitten vielä yksi ketju ajastimena, joka vanhentumisen jälkeen tappaa vastaanoton lanka, jos se on vielä elossa. Vaikka tämä menetelmä toimii, se ei todennäköisesti ole kaikkein siro tapa suorittaa tehtävä.

Sen sijaan, että tapaisin langan, joka on estetty vastaanottomenetelmällä, halusin suloisemman ratkaisun - sellaisen, joka avaisi vastaanottomenetelmän eston. Tämän toteuttamiseksi tarvitsin säiettä, joka pystyi lähettämään datagrammi-viestin vastaanottavalle säikeelle estämään vastaanottavan säikeen eston aikakatkaisun jälkeen. Aikakatkaisulanka toteutetaan omana luokkana, ja vastaanottoketju luo aikakatkaisuluokan esiintymän juuri ennen estämistä vastaanottomenetelmässä. Seuraava koodi näyttää aikakatkaisun luokan toteutuksen. Huomaa, että lyhyyden vuoksi poikkeusten käsittely jätetään pois.

tuo java.io. *; tuo java.net. *; tuo java.lang. *; public class DatagramWatchdogTimer toteuttaa Runnable {DatagramWatchdogTimer (int timeoutSeconds) heittää SocketException {timeout = timeoutSeconds; socket = uusi DatagramSocket (); datagramPort = socket.getLocalPort (); Lanka thisThread = uusi lanka (tämä); thisThread.start (); } public int getPort () {return datagramPort; } public void run () {// luo vakiovastausviesti, joka osoittaa // viestin tuli DatagramWatchdogTimer // -tapauksestani, nollani riittää. Merkkijono responseStr = uusi kokonaisluku (0) .toString (); tavu [] vastausBuf = uusi tavu [vastausStr.pituus ()]; answerStr.getBytes (0, answerStr.length (), answerBuff, 0); int vastauspituus = vastausStr.pituus (); // vastaanottaa viesti vastaanottavasta säikeestä. // tämä on välttämätöntä, jotta tiedämme, miten eston // viesti lähetetään takaisin siihen. tavu [] puskuri = uusi bute [128]; DatagramPacket-paketti = uusi DatagramPacket (puskuri, puskuri.pituus); pistorasia. vastaanota (paketti); // odota aikakatkaisua sekuntien määrä ja lähetä sitten esto // viesti takaisin. Thread.sleep (aikakatkaisu * 1000); int requestorPort = packet.getPort (); InetAddress requestorAddress = packet.getAddress (); DatagramPacket sendPacket = uusi DatagramPacket (AnswBuff, AnswerLength, requestorAddress, requestorPort); DatagramSocket sendSocket = uusi DatagramSocket (); sendSocket.send (sendPacket); } yksityinen aikakatkaisu; yksityinen int datagramPort; yksityinen DatagramSocket-liitäntä; } 

Kuten yllä mainittiin, aina, kun sovelluksesi on vastaanotettava datagrammi-viesti, se voi luoda DatagramWatchdogTimer luokassa asettaa aikakatkaisuajan. Jos sovellus ei saa oikeaa viestiä aikakatkaisun sekuntien kuluessa, se kumoutuu vastaanottamalla eston viestin DatagramWatchdogTimer luokassa.

Tässä on esimerkki:

// sovelluskoodi int timeoutSeconds = 5; InetAddress myAddress = InetAddress.getByName (""); // luo ajastinluokan DatagramWatchdogTimer ilmentymä wdTimer = new DatagramWatchdogTimer (timeoutSeconds); int wdPort = wdTimer.getPort (); // lähetä viesti wdTimerille ajastimen käynnistämiseksi // msgBuff voi olla mitä haluat. Merkkijono msgString = uusi merkkijono ("aika minulle"); tavu [] msgBuff = uusi tavu [msgString.length ()]; msgString.getBytes (0, msgString.length (), msgBuff, 0); DatagramSocket-liitäntä = uusi DatagramSocket (); DatagramPacket wdPacket = uusi DatagramPacket (msgBuff, msgLength, myAddress, wdPort); socket.send (wdPacket); // nyt voit lukea pistorasiasta ja saada jonkin verran varmuutta //, että estät vain timeoutSeconds. tavu [] puskuri = uusi tavu [1024]; DatagramPacket-paketti = uusi DatagramPacket (puskuri, puskuri.pituus); pistorasia. vastaanota (paketti); jos (myAddress.equals (packet.getAddress) == true) {// sai viestin ajastinobjektista} else {// sai oikean viestin} 

Kun käytät tätä tekniikkaa, muista käyttää samaa DatagramSocketia sekä DatagramWatchdogTimer-objektille lähettämiseen että datagrammien vastaanottamiseen. Tämä varmistaa, että DatagramWatchdogTimer-objekti tietää, mihin eston viesti lähetetään. Myös yllä esitetyssä näytekoodissa käytettiin dynaamisesti allokoitua porttia instantoimalla DatagramSocket () ilman argumentteja. Se toimii myös valitsemallasi tunnetulla portilla, kuten DatagramSocket (8000). Lopuksi, haluat ehkä ajastinobjektin lähettävän useamman kuin yhden eston viestin - vain lisätäksesi mahdollisuuksia saada sovellus vastaanottajalle. Tämän ei pitäisi olla ongelma, koska ajastinobjekti toimii säikeenä samalla koneella sovelluksen kanssa.

Albert Lopez oli Sun Microsystemsin teknisen henkilöstön jäsen vuosina 1989–1995. Hän on äskettäin tullut tietojärjestelmien henkilökunnan jäseneksi Chicagon kauppakeskukseen, jossa hän on seuraavan sukupolven Java-kehitystiimin johtava jäsen. sähköinen kaupankäyntijärjestelmä Java-sovelluksella.

Tämän tarinan, "Java Tip 18: Timeout-ominaisuuden käyttöönotto JDK 1.0.2 DatagramSocketille", julkaisi alun perin JavaWorld.