Programmering

Java Tips 18: Implementering av en tidsavbruddsfunksjon for JDK 1.0.2 DatagramSocket

Hvis du har utviklet et Java-program som bruker Datagram-kontakten til å sende og motta meldinger, kan du ha opplevd behovet for å implementere en tidsavbruddsfunksjon for å oppheve blokkeringen av DatagramSocket motta metoden. Uten en tidsavbruddsfunksjon, vil applikasjonen din blokkere til den mottar en melding, og siden levering av Datagram ikke er garantert, kan applikasjonen din blokkere veldig lenge. Dette Java-tipet vil beskrive en teknikk for tidsavbrudd og blokkering av DatagramSocket motta metoden.

Du har sannsynligvis allerede gjettet at denne teknikken vil bruke tråder. Trådprogrammering i Java er ganske hyggelig. Man kan sammenligne det med gleden ved å stå på ski ved Lake Tahoe eller å seile nær kysten av Santa Cruz. (OK, kanskje det ikke er det at hyggelig, men det er fortsatt veldig gøy!)

Når du vurderer en metode for å oppnå tidsavbruddsfunksjonen, er kanskje den første og mest åpenbare ordningen som du kommer til å tenke på å plassere DatagramSocket-mottaksfunksjonaliteten i en egen tråd og deretter starte enda en tråd som en tidtaker som ved utløp vil drepe mottakelsen. tråden hvis den fremdeles lever. Selv om denne metoden vil fungere, er det sannsynligvis ikke den mest elegante måten å utføre oppgaven på.

I stedet for å drepe en tråd som er blokkert på mottaksmetoden, ønsket jeg en mer grasiøs løsning - en som ville blokkere mottaksmetoden. For å oppnå dette trengte jeg en tråd som kunne sende en datagrammelding til mottakertråden for å oppheve blokkeringen av mottakertråden etter at tidsavbruddsperioden var utløpt. Timeout-tråden er implementert som sin egen klasse, og mottakertråden oppretter en forekomst av timeout-klassen like før den blokkeres på mottaksmetoden. Følgende kode viser implementeringen av timeoutklassen. Vær oppmerksom på at for kortfattethet er unntakshåndtering utelatt.

importer java.io. *; importer java.net. *; importer java.lang. *; offentlig klasse DatagramWatchdogTimer implementerer Runnable {DatagramWatchdogTimer (int timeoutSeconds) kaster SocketException {timeout = timeoutSeconds; socket = ny DatagramSocket (); datagramPort = socket.getLocalPort (); Tråd thisThread = ny tråd (dette); thisThread.start (); } public int getPort () {return datagramPort; } public void run () {// opprett en standard svarmelding som indikerer // meldingen kom fra DatagramWatchdogTimer // i mitt tilfelle er det null nok. Streng replyStr = nytt heltall (0) .toString (); byte [] replyBuf = ny byte [replyStr.length ()]; replyStr.getBytes (0, replyStr.length (), replyBuff, 0); int replyLength = replyStr.length (); // motta en melding fra mottakertråden. // dette er nødvendig slik at vi vet hvordan vi skal sende oppblokkeringen // meldingen tilbake til den. byte [] buffer = ny bute [128]; DatagramPacket-pakke = ny DatagramPacket (buffer, buffer.length); socket.receive (pakke); // ventetid timeout antall sekunder, og send deretter en blokkering // melding tilbake. Thread.sleep (timeout * 1000); int requestorPort = packet.getPort (); InetAddress requestorAddress = packet.getAddress (); DatagramPacket sendPacket = ny DatagramPacket (replyBuff, replyLength, requestorAddress, requestorPort); DatagramSocket sendSocket = ny DatagramSocket (); sendSocket.send (sendPacket); } privat int timeout; privat int datagramPort; privat DatagramSocket-kontakt; } 

Som nevnt ovenfor, når applikasjonen din trenger å motta en datagrammelding, kan den opprette en forekomst av DatagramWatchdogTimer klasse for å sette en tidsavbruddsperiode. Hvis applikasjonen ikke mottar en reell melding innen timeout sekunder, vil den oppheve blokkeringen ved å motta en blokkeringsmelding fra DatagramWatchdogTimer klasse.

Her er et eksempel:

// applikasjonskode int timeoutSeconds = 5; InetAddress myAddress = InetAddress.getByName (""); // lage en forekomst av tidtakerklassen DatagramWatchdogTimer wdTimer = ny DatagramWatchdogTimer (timeoutSeconds); int wdPort = wdTimer.getPort (); // send en melding til wdTimer for å få timeren i gang // msgBuff kan være hva du vil. Streng msgString = ny streng ("tid meg"); byte [] msgBuff = ny byte [msgString.length ()]; msgString.getBytes (0, msgString.length (), msgBuff, 0); DatagramSocket-sokkel = ny DatagramSocket (); DatagramPacket wdPacket = ny DatagramPacket (msgBuff, msgLength, myAddress, wdPort); socket.send (wdPacket); // nå kan du lese fra stikkontakten og ha litt forsikring // om at du bare vil blokkere for timeoutSeconds. byte [] buffer = ny byte [1024]; DatagramPacket-pakke = ny DatagramPacket (buffer, buffer.length); socket.receive (pakke); hvis (myAddress.equals (packet.getAddress) == true) {// mottatt melding fra tidsurobjekt} ellers {// mottatt en reell melding} 

Når du bruker denne teknikken, må du bruke den samme DatagramSocket for både sending til DatagramWatchdogTimer-objektet og for mottak av datagrammer. Dette sørger for at DatagramWatchdogTimer-objektet vet hvor du skal sende meldingen om blokkering. I eksempelkoden vist ovenfor ble en dynamisk tildelt port brukt ved å starte DatagramSocket () uten noen argumenter. Det vil også fungere ved hjelp av en velkjent port etter eget valg, for eksempel DatagramSocket (8000). Til slutt vil du kanskje at tidsurobjektet skal sende mer enn én blokkeringsmelding - bare for å øke sjansene for at det blir mottatt av applikasjonen. Dette burde ikke være et problem siden tidsurobjektet kjører som en tråd på samme maskin som applikasjonen.

Albert Lopez var medlem av det tekniske personalet i Sun Microsystems fra 1989 til 1995. Han har nylig sluttet seg til informasjonssystemets ansatte ved Chicago Board of Trade, hvor han er et ledende medlem av Java-utviklingsteamet som utvikler neste generasjon. elektronisk handelssystem ved bruk av Java.

Denne historien, "Java Tips 18: Implementing a timeout feature for JDK 1.0.2 DatagramSocket" ble opprinnelig utgitt av JavaWorld.

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