Προγραμματισμός

Java Tip 18: Εφαρμογή μιας δυνατότητας χρονικού ορίου για το JDK 1.0.2 DatagramSocket

Εάν έχετε αναπτύξει μια εφαρμογή Java που χρησιμοποιεί την υποδοχή Datagram για να στέλνετε και να λαμβάνετε μηνύματα, τότε ενδέχεται να έχετε αντιμετωπίσει την ανάγκη εφαρμογής ενός χρονικού ορίου για να ξεμπλοκάρετε το Υποδοχή λήψη μεθόδου. Χωρίς δυνατότητα λήξης χρονικού ορίου, η εφαρμογή σας θα αποκλείστηκε έως ότου λάβει ένα μήνυμα και επειδή η παράδοση των δεδομένων δεν είναι εγγυημένη, η εφαρμογή σας θα μπορούσε να αποκλείσει για πολύ μεγάλο χρονικό διάστημα. Αυτή η Συμβουλή Java θα περιγράψει μια τεχνική για το χρονικό όριο και την απεμπλοκή του Υποδοχή λήψη μεθόδου.

Πιθανότατα έχετε ήδη μαντέψει ότι αυτή η τεχνική θα χρησιμοποιεί νήματα. Ο προγραμματισμός νημάτων στην Java είναι αρκετά ευχάριστος. Θα μπορούσε κανείς να το συγκρίνει με τις χαρές του σκι στη λίμνη Tahoe ή της ιστιοπλοΐας κοντά στην ακτή της Santa Cruz. (Εντάξει, ίσως δεν είναι ότι ευχάριστο, αλλά εξακολουθεί να είναι πολύ διασκεδαστικό!)

Όταν σκέφτεστε μια μέθοδο για να ολοκληρώσετε τη λειτουργία χρονικού ορίου, ίσως το πρώτο και πιο προφανές σχήμα που έρχεται στο μυαλό είναι να τοποθετήσετε τη λειτουργία λήψης DatagramSocket σε ένα ξεχωριστό νήμα και στη συνέχεια να ξεκινήσετε ένα ακόμη νήμα ως χρονοδιακόπτη που, κατά τη λήξη, θα σκότωνε τη λήψη νήμα εάν είναι ακόμα ζωντανό. Ενώ αυτή η μέθοδος θα λειτουργήσει, πιθανότατα δεν είναι ο πιο χαριτωμένος τρόπος για να ολοκληρώσετε την εργασία.

Αντί να σκοτώσω ένα νήμα που είναι μπλοκαρισμένο στη μέθοδο λήψης, ήθελα μια πιο χαριτωμένη λύση - μια λύση που θα ξεμπλοκάρει τη μέθοδο λήψης. Για να το πετύχω αυτό, χρειαζόμουν ένα νήμα που ήταν ικανό να στείλει ένα μήνυμα datagram στο νήμα λήψης για να ξεκλειδώσω το νήμα λήψης μετά τη λήξη μιας περιόδου λήξης. Το νήμα χρονικού ορίου εφαρμόζεται ως δική του κλάση και το νήμα λήψης δημιουργεί μια παρουσία της τάξης χρονικού ορίου λίγο πριν μπλοκάρει τη μέθοδο λήψης. Ο παρακάτω κώδικας δείχνει την εφαρμογή τάξης χρονικού ορίου. Σημειώστε ότι, για συντομία, παραλείπεται ο χειρισμός εξαιρέσεων.

εισαγωγή java.io. *; εισαγωγή java.net. *; εισαγωγή java.lang. *; δημόσια τάξη DatagramWatchdogTimer υλοποιεί το Runnable {DatagramWatchdogTimer (int timeoutSeconds) ρίχνει το SocketException {timeout = timeoutSeconds; socket = νέο DatagramSocket (); datagramPort = socket.getLocalPort (); Thread thisThread = νέο νήμα (αυτό); thisThread.start (); } δημόσιο int getPort () {return datagramPort; } public void run () {// δημιουργήστε ένα τυπικό μήνυμα απάντησης που υποδεικνύει // το μήνυμα προήλθε από το DatagramWatchdogTimer // στην περίπτωσή μου, αρκεί το μηδέν. String replyStr = new Integer (0) .toString (); byte [] replyBuf = νέο byte [replyStr.length ()]; replyStr.getBytes (0, replyStr.length (), replyBuff, 0); int replyLength = replyStr.length (); // λάβετε ένα μήνυμα από το νήμα λήψης. // αυτό είναι απαραίτητο, ώστε να ξέρουμε πώς να στείλουμε το μήνυμα ξεμπλοκαρίσματος // σε αυτό. byte [] buffer = νέο bute [128]; DatagramPacket packet = νέο DatagramPacket (buffer, buffer.length); socket.receive (πακέτο); // αναμονή χρονικού ορίου δευτερολέπτων και, στη συνέχεια, αποστολή μηνύματος αποκλεισμού //. Thread.sleep (χρονικό όριο * 1000); int requestorPort = packet.getPort (); InetAddress requestorAddress = packet.getAddress (); DatagramPacket sendPacket = νέο DatagramPacket (replyBuff, replyLength, requestorAddress, requestorPort); DatagramSocket sendSocket = νέο DatagramSocket (); sendSocket.send (sendPacket); } ιδιωτικό χρονικό όριο λήξης ιδιωτικό int datagramPort; ιδιωτική υποδοχή DatagramSocket. } 

Όπως αναφέρθηκε παραπάνω, κάθε φορά που η αίτησή σας χρειάζεται να λαμβάνει ένα μήνυμα datagram, μπορεί να δημιουργήσει μια παρουσία του DatagramWatchdogTimer τάξη για να ορίσετε μια χρονική περίοδο. Εάν η εφαρμογή δεν λάβει πραγματικό μήνυμα εντός δευτερολέπτου χρονικού ορίου, θα ξεμπλοκαριστεί λαμβάνοντας ένα μήνυμα αποκλεισμού από το DatagramWatchdogTimer τάξη.

Εδώ είναι ένα παράδειγμα:

// κωδικός εφαρμογής int timeoutSeconds = 5; InetAddress myAddress = InetAddress.getByName (""); // δημιουργήστε μια παρουσία της κλάσης χρονοδιακόπτη DatagramWatchdogTimer wdTimer = νέο DatagramWatchdogTimer (timeoutSeconds); int wdPort = wdTimer.getPort (); // στείλτε ένα μήνυμα στο wdTimer για να ξεκινήσετε το χρονόμετρο // msgBuff μπορεί να είναι ό, τι θέλετε. String msgString = new String ("time me"); byte [] msgBuff = νέο byte [msgString.length ()]; msgString.getBytes (0, msgString.length (), msgBuff, 0); DatagramSocket socket = νέο DatagramSocket (); DatagramPacket wdPacket = νέο DatagramPacket (msgBuff, msgLength, myAddress, wdPort); socket.send (wdPacket); // τώρα μπορείτε να διαβάσετε από την πρίζα και να έχετε κάποια διαβεβαίωση // ότι θα αποκλείσετε μόνο για timeoutSeconds. byte [] buffer = νέο byte [1024]; DatagramPacket packet = νέο DatagramPacket (buffer, buffer.length); socket.receive (πακέτο); if (myAddress.equals (packet.getAddress) == true) {// έλαβε μήνυμα από το χρονόμετρο αντικείμενο} αλλιώς {// έλαβε ένα πραγματικό μήνυμα} 

Όταν χρησιμοποιείτε αυτήν την τεχνική, βεβαιωθείτε ότι χρησιμοποιείτε το ίδιο DatagramSocket τόσο για την αποστολή στο αντικείμενο DatagramWatchdogTimer όσο και για τη λήψη δεδομένων. Αυτό διασφαλίζει ότι το αντικείμενο DatagramWatchdogTimer ξέρει πού να στείλει το μήνυμα κατάργησης αποκλεισμού. Επίσης, στο δείγμα κώδικα που εμφανίζεται παραπάνω, χρησιμοποιήθηκε μια δυναμικά κατανεμημένη θύρα με την παρουσίαση του DatagramSocket () χωρίς ορίσματα. Θα λειτουργούσε επίσης χρησιμοποιώντας ένα γνωστό λιμάνι της επιλογής σας, όπως το DatagramSocket (8000). Τέλος, ίσως θέλετε το αντικείμενο χρονοδιακόπτη να στείλει περισσότερα από ένα μηνύματα αποκλεισμού - για να αυξήσετε τις πιθανότητες να ληφθεί από την εφαρμογή. Αυτό δεν πρέπει να αποτελεί πρόβλημα, καθώς το αντικείμενο χρονοδιακόπτη εκτελείται ως νήμα στον ίδιο υπολογιστή με την εφαρμογή.

Ο Albert Lopez ήταν μέλος του τεχνικού προσωπικού της Sun Microsystems από το 1989 έως το 1995. Πρόσφατα προσχώρησε στο προσωπικό του Information Systems στο Συμβούλιο Εμπορίου του Σικάγου, όπου είναι επικεφαλής της ομάδας ανάπτυξης Java που αναπτύσσει την επόμενη γενιά σύστημα ηλεκτρονικών συναλλαγών χρησιμοποιώντας Java.

Αυτή η ιστορία, "Συμβουλή Java 18: Εφαρμογή μιας δυνατότητας χρονικού ορίου για το JDK 1.0.2 DatagramSocket" δημοσιεύθηκε αρχικά από το JavaWorld.