Πώς να δημιουργήσετε μια εφαρμογή δικτύου σε Java (με εικόνες)

Πίνακας περιεχομένων:

Πώς να δημιουργήσετε μια εφαρμογή δικτύου σε Java (με εικόνες)
Πώς να δημιουργήσετε μια εφαρμογή δικτύου σε Java (με εικόνες)

Βίντεο: Πώς να δημιουργήσετε μια εφαρμογή δικτύου σε Java (με εικόνες)

Βίντεο: Πώς να δημιουργήσετε μια εφαρμογή δικτύου σε Java (με εικόνες)
Βίντεο: Στιγμιότυπο οθόνης από συσκευή Android 2024, Ενδέχεται
Anonim

Η εγγραφή κώδικα που εκτελείται σε μια συγκεκριμένη συσκευή είναι πολύ ικανοποιητική. Αλλά, η συγγραφή κώδικα που εκτελείται σε πολλές συσκευές που επικοινωνούν μεταξύ τους είναι απλώς επιβεβαιωτική για τη ζωή. Αυτό το άρθρο θα σας διδάξει πώς να συνδέετε και να ανταλλάσσετε μηνύματα μέσω δικτύου χρησιμοποιώντας πρωτόκολλο ελέγχου μετάδοσης (TCP).

Σε αυτό το άρθρο, θα ρυθμίσετε μια εφαρμογή που θα συνδέει τον υπολογιστή σας στον εαυτό του και, ουσιαστικά, θα τον κάνει τρελό - μιλήστε μόνος του. Θα μάθετε επίσης τη διαφορά μεταξύ των δύο πιο διαδεδομένων ροών για δικτύωση στην Java και τον τρόπο λειτουργίας τους.

Ροές δεδομένων και αντικειμένων

Πριν ξεκινήσετε τον κωδικό, πρέπει να γίνει διάκριση μεταξύ των δύο ρευμάτων που χρησιμοποιούνται στο άρθρο.

Ροές δεδομένων

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

Ροές αντικειμένων

Οι ροές αντικειμένων επεξεργάζονται πρωτόγονους τύπους δεδομένων και αντικείμενα που υλοποιούνται

Σειριακοποιήσιμο

διεπαφή. Τα δεδομένα που αποστέλλονται μέσω ροών αντικειμένων σειριοποιούνται αυτόματα και αποκεντρώνουν, πράγμα που διευκολύνει τη μεταφορά πολύπλοκων δεδομένων. Όμως, οι ροές αντικειμένων μπορούν να επικοινωνούν μόνο με διακομιστές και πελάτες που είναι γραμμένες σε Java. Επίσης,

ObjectOutputStream

κατά την προετοιμασία, στέλνει μια κεφαλίδα στο

InputStream

του άλλου μέρους το οποίο, κατά την προετοιμασία, αποκλείει την εκτέλεση μέχρι να ληφθεί η κεφαλίδα.

Βήματα

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step1
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step1

Βήμα 1. Δημιουργήστε μια τάξη

Δημιουργήστε μια τάξη και ονομάστε την όπως θέλετε. Σε αυτό το άρθρο, θα ονομαστεί

NetworkAppExample

δημόσια τάξη NetworkAppExample {}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step2
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step2

Βήμα 2. Δημιουργήστε μια κύρια μέθοδο

Δημιουργήστε μια κύρια μέθοδο και δηλώστε ότι μπορεί να περιλαμβάνει εξαιρέσεις

Εξαίρεση

τύπο και οποιαδήποτε υποκλάση του - όλες εξαιρέσεις. Αυτό θεωρείται κακή πρακτική, αλλά είναι αποδεκτή για παραδείγματα γυμνού.

δημόσια τάξη NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {}}

Δημιουργήστε μια εφαρμογή δικτύου σε Java Step3
Δημιουργήστε μια εφαρμογή δικτύου σε Java Step3

Βήμα 3. Δήλωση διεύθυνσης διακομιστή

Αυτό το παράδειγμα θα χρησιμοποιήσει τη διεύθυνση τοπικού κεντρικού υπολογιστή και έναν αυθαίρετο αριθμό θύρας. Ο αριθμός θύρας πρέπει να κυμαίνεται από 0 έως 65535 (συμπεριλαμβανομένου). Ωστόσο, οι αριθμοί θυρών προς αποφυγή κυμαίνονται από 0 έως 1023 (συμπεριλαμβανομένων) επειδή είναι δεσμευμένες θύρες συστήματος.

public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; }}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step4
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step4

Βήμα 4. Δημιουργήστε έναν διακομιστή

Ο διακομιστής είναι δεσμευμένος στη διεύθυνση και τη θύρα και ακούει τις εισερχόμενες συνδέσεις. Στην Java,

ServerSocket

αντιπροσωπεύει το τελικό σημείο του διακομιστή και η λειτουργία του είναι η αποδοχή νέων συνδέσεων.

ServerSocket

δεν έχει ροές για ανάγνωση και αποστολή δεδομένων επειδή δεν αντιπροσωπεύει σύνδεση μεταξύ διακομιστή και πελάτη.

εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); }}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step5
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step5

Βήμα 5. Έναρξη λειτουργίας διακομιστή καταγραφής

Για σκοπούς καταγραφής, εκτυπώστε στην κονσόλα του διακομιστή που έχει ξεκινήσει.

εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); }}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step6
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step6

Βήμα 6. Δημιουργήστε έναν πελάτη

Ο πελάτης είναι δεσμευμένος στη διεύθυνση και τη θύρα ενός διακομιστή και ακούει πακέτα (μηνύματα) μετά τη δημιουργία της σύνδεσης. Στην Java,

Πρίζα

αντιπροσωπεύει είτε ένα τελικό σημείο από την πλευρά του πελάτη που συνδέεται με τον διακομιστή είτε μια σύνδεση (από διακομιστή) με πελάτη και χρησιμοποιείται για επικοινωνία με το μέρος στο άλλο άκρο.

εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). }}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step7
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step7

Βήμα 7. Προσπάθεια σύνδεσης καταγραφής

Για λόγους καταγραφής, εκτυπώστε στην κονσόλα ότι η σύνδεση έχει επιχειρηθεί.

εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); }}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step8
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step8

Βήμα 8. Δημιουργία σύνδεσης

Οι πελάτες δεν θα συνδεθούν ποτέ, εκτός εάν ο διακομιστής ακούει και αποδέχεται, με άλλα λόγια, δημιουργεί συνδέσεις. Στην Java, οι συνδέσεις δημιουργούνται χρησιμοποιώντας

αποδέχομαι()

μέθοδος για

ServerSocket

τάξη. Η μέθοδος θα αποκλείσει την εκτέλεση μέχρι να συνδεθεί ένας πελάτης.

εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); }}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step9
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step9

Βήμα 9. Καταγράψτε τη σύνδεση

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

εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); }}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step10
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step10

Βήμα 10. Προετοιμάστε ροές επικοινωνίας

Η επικοινωνία πραγματοποιείται μέσω ροών και, σε αυτήν την εφαρμογή, οι ακατέργαστες ροές (σύνδεσης από) διακομιστή (πελάτη) και πελάτη πρέπει να συνδεθούν με ροές δεδομένων ή αντικειμένων. Θυμηθείτε, και τα δύο μέρη πρέπει να χρησιμοποιούν τον ίδιο τύπο ροής.

  • Ροές δεδομένων

    εισαγωγή java.io. DataInputStream; εισαγωγή java.io. DataOutputStream; εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); DataOutputStream clientOut = νέο DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = νέο DataInputStream (client.getInputStream ()); DataOutputStream serverOut = νέο DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = νέο DataInputStream (connection.getInputStream ()); }}

  • Ροές αντικειμένων

    Όταν χρησιμοποιούνται πολλαπλές ροές αντικειμένων, οι ροές εισόδου πρέπει να αρχικοποιηθούν με την ίδια σειρά με τις ροές εξόδου, επειδή

    ObjectOutputStream

    στέλνει μια κεφαλίδα στο άλλο μέρος και

    ObjectInputStream

    μπλοκάρει την εκτέλεση μέχρι να διαβάσει την κεφαλίδα.

    εισαγωγή java.io. ObjectInputStream; εισαγωγή java.io. ObjectOutputStream; εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); ObjectOutputStream clientOut = νέο ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = νέο ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = νέο ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = νέο ObjectInputStream (connection.getInputStream ()); }}

    Η παραγγελία όπως καθορίζεται στον παραπάνω κώδικα μπορεί να είναι πιο εύκολο να θυμηθεί - αρχικοποιήστε πρώτα τις ροές εξόδου και μετά τις ροές εισόδου με την ίδια σειρά. Ωστόσο, μια άλλη σειρά για την αρχικοποίηση των ροών αντικειμένων είναι η ακόλουθη:

    ObjectOutputStream clientOut = νέο ObjectOutputStream (client.getOutputStream ()); ObjectInputStream serverIn = νέο ObjectInputStream (connection.getInputStream ()); ObjectOutputStream serverOut = νέο ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = νέο ObjectInputStream (client.getInputStream ());

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step11
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step11

Βήμα 11. Καταγράψτε ότι η επικοινωνία είναι έτοιμη

Για σκοπούς καταγραφής, εκτυπώστε στην κονσόλα ότι η επικοινωνία είναι έτοιμη.

// παράλειψη κωδικού εισαγωγής java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); // ο κωδικός παραλείπεται System.out.println ("Η επικοινωνία είναι έτοιμη."); }}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step12
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step12

Βήμα 12. Δημιουργήστε ένα μήνυμα

Σε αυτήν την εφαρμογή,

Γειά σου Κόσμε

κείμενο θα σταλεί στον διακομιστή είτε ως

ψηφιόλεξη

ή

Σειρά

Το Δηλώστε μια μεταβλητή του τύπου που εξαρτάται από τη ροή που χρησιμοποιείται. Χρήση

ψηφιόλεξη

για ροές δεδομένων και

Σειρά

για ροές αντικειμένων.

  • Ροές δεδομένων

    Χρησιμοποιώντας ροές δεδομένων, η σειριοποίηση γίνεται με τη μετατροπή αντικειμένων σε πρωτόγονους τύπους δεδομένων ή α

    Σειρά

    Το Σε αυτήν την περίπτωση,

    Σειρά

    μετατρέπεται σε

    ψηφιόλεξη

    αντί να γράφεται χρησιμοποιώντας

    writeBytes ()

    μέθοδο για να δείξει πώς θα γινόταν με άλλα αντικείμενα, όπως εικόνες ή άλλα αρχεία.

    εισαγωγή java.io. DataInputStream; εισαγωγή java.io. DataOutputStream; εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); DataOutputStream clientOut = νέο DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = νέο DataInputStream (client.getInputStream ()); DataOutputStream serverOut = νέο DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = νέο DataInputStream (connection.getInputStream ()); System.out.println ("Η επικοινωνία είναι έτοιμη."); byte messageOut = "Hello World".getBytes (); }}

  • Ροές αντικειμένων

    εισαγωγή java.io. ObjectInputStream; εισαγωγή java.io. ObjectOutputStream; εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); ObjectOutputStream clientOut = νέο ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = νέο ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = νέο ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = νέο ObjectInputStream (connection.getInputStream ()); System.out.println ("Η επικοινωνία είναι έτοιμη."); String messageOut = "Hello World"; }}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step13
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step13

Βήμα 13. Στείλτε το μήνυμα

Γράψτε δεδομένα στη ροή εξόδου και ξεπλύνετε τη ροή για να διασφαλίσετε ότι τα δεδομένα έχουν γραφτεί εξ ολοκλήρου.

  • Ροές δεδομένων

    Το μήκος ενός μηνύματος πρέπει να σταλεί πρώτα, ώστε το άλλο μέρος να γνωρίζει πόσα bytes πρέπει να διαβάσει. Αφού αποσταλεί το μήκος ως πρωτόγονος ακέραιος τύπος, μπορούν να σταλούν byte.

    εισαγωγή java.io. DataInputStream; εισαγωγή java.io. DataOutputStream; εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); DataOutputStream clientOut = νέο DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = νέο DataInputStream (client.getInputStream ()); DataOutputStream serverOut = νέο DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = νέο DataInputStream (connection.getInputStream ()); System.out.println ("Η επικοινωνία είναι έτοιμη."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); }}

  • Ροές αντικειμένων

    εισαγωγή java.io. ObjectInputStream; εισαγωγή java.io. ObjectOutputStream; εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); ObjectOutputStream clientOut = νέο ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = νέο ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = νέο ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = νέο ObjectInputStream (connection.getInputStream ()); System.out.println ("Η επικοινωνία είναι έτοιμη."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); }}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step14
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step14

Βήμα 14. Καταγράψτε το μήνυμα που στάλθηκε

Για σκοπούς καταγραφής, εκτυπώστε το μήνυμα που έχει σταλεί στην κονσόλα.

  • Ροές δεδομένων

    εισαγωγή java.io. DataInputStream; εισαγωγή java.io. DataOutputStream; εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); DataOutputStream clientOut = νέο DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = νέο DataInputStream (client.getInputStream ()); DataOutputStream serverOut = νέο DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = νέο DataInputStream (connection.getInputStream ()); System.out.println ("Η επικοινωνία είναι έτοιμη."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Το μήνυμα στάλθηκε στον διακομιστή:" + νέο String (messageOut)); }}

  • Ροές αντικειμένων

    εισαγωγή java.io. ObjectInputStream; εισαγωγή java.io. ObjectOutputStream; εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); ObjectOutputStream clientOut = νέο ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = νέο ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = νέο ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = νέο ObjectInputStream (connection.getInputStream ()); System.out.println ("Η επικοινωνία είναι έτοιμη."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Το μήνυμα στάλθηκε στον διακομιστή:" + messageOut); }}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step15
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step15

Βήμα 15. Διαβάστε το μήνυμα

Διαβάστε δεδομένα από τη ροή εισόδου και μετατρέψτε τα. Δεδομένου ότι γνωρίζουμε ακριβώς τον τύπο των σταλθέντων δεδομένων, είτε θα δημιουργήσουμε ένα

Σειρά

από

ψηφιόλεξη

ή καστ

Αντικείμενο

προς το

Σειρά

χωρίς έλεγχο, ανάλογα με τη ροή που χρησιμοποιείται.

  • Ροές δεδομένων

    Καθώς το μήκος στάλθηκε πρώτα και τα bytes μετά, η ανάγνωση πρέπει να γίνει με την ίδια σειρά. Σε περίπτωση που το μήκος είναι μηδέν, δεν υπάρχει τίποτα για ανάγνωση. Το αντικείμενο αποκεντρώνεται όταν τα byte μετατρέπονται ξανά σε ένα παράδειγμα, στην περίπτωση αυτή, του

    Σειρά

    εισαγωγή java.io. DataInputStream; εισαγωγή java.io. DataOutputStream; εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); DataOutputStream clientOut = νέο DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = νέο DataInputStream (client.getInputStream ()); DataOutputStream serverOut = νέο DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = νέο DataInputStream (connection.getInputStream ()); System.out.println ("Η επικοινωνία είναι έτοιμη."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Το μήνυμα στάλθηκε στον διακομιστή:" + νέο String (messageOut)); int length = serverIn.readInt (); εάν (μήκος> 0) {byte messageIn = νέο byte [μήκος]; serverIn.readFully (messageIn, 0, messageIn.length); }}}

  • Ροές αντικειμένων

    εισαγωγή java.io. ObjectInputStream; εισαγωγή java.io. ObjectOutputStream; εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); ObjectOutputStream clientOut = νέο ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = νέο ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = νέο ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = νέο ObjectInputStream (connection.getInputStream ()); System.out.println ("Η επικοινωνία είναι έτοιμη."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Το μήνυμα στάλθηκε στον διακομιστή:" + messageOut); String messageIn = (String) serverIn.readObject (); }}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step16
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step16

Βήμα 16. Καταγράψτε το μήνυμα ανάγνωσης

Για σκοπούς καταγραφής, εκτυπώστε το μήνυμα που έχει ληφθεί στην κονσόλα και εκτυπώστε το περιεχόμενό του.

  • Ροές δεδομένων

    εισαγωγή java.io. DataInputStream; εισαγωγή java.io. DataOutputStream; εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); DataOutputStream clientOut = νέο DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = νέο DataInputStream (client.getInputStream ()); DataOutputStream serverOut = νέο DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = νέο DataInputStream (connection.getInputStream ()); System.out.println ("Η επικοινωνία είναι έτοιμη."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Το μήνυμα στάλθηκε στον διακομιστή:" + νέο String (messageOut)); int length = serverIn.readInt (); εάν (μήκος> 0) {byte messageIn = νέο byte [μήκος]; serverIn.readFully (messageIn, 0, messageIn.length); System.out.println ("Μήνυμα που ελήφθη από τον πελάτη:" + νέο String (messageIn)); }}}

  • Ροές αντικειμένων

    εισαγωγή java.io. ObjectInputStream; εισαγωγή java.io. ObjectOutputStream; εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); ObjectOutputStream clientOut = νέο ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = νέο ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = νέο ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = νέο ObjectInputStream (connection.getInputStream ()); System.out.println ("Η επικοινωνία είναι έτοιμη."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Το μήνυμα στάλθηκε στον διακομιστή:" + messageOut); String messageIn = (String) serverIn.readObject (); System.out.println ("Μήνυμα που ελήφθη από τον πελάτη:" + messageIn); }}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step17
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step17

Βήμα 17. Αποσυνδέστε τις συνδέσεις

Η σύνδεση αποσυνδέεται όταν ένα μέρος κλείνει τις ροές του. Στην Java, κλείνοντας τη ροή εξόδου, κλείνουν επίσης η σχετική υποδοχή και η ροή εισόδου. Μόλις ένα μέρος στο άλλο άκρο διαπιστώσει ότι η σύνδεση είναι νεκρή, πρέπει επίσης να κλείσει το ρεύμα εξόδου του, για να αποτρέψει διαρροές μνήμης.

// παράλειψη κωδικού εισαγωγής java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); // ο κωδικός παραλείπεται System.out.println ("Η επικοινωνία είναι έτοιμη."); // παραλείπεται ο κωδικός clientOut.close (); serverOut.close (); }}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step18 V2
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step18 V2

Βήμα 18. Αποσύνδεση καταγραφής

Για λόγους καταγραφής, η εκτύπωση στις συνδέσεις της κονσόλας έχει αποσυνδεθεί.

// παράλειψη κωδικού εισαγωγής java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); // ο κωδικός παραλείπεται System.out.println ("Η επικοινωνία είναι έτοιμη."); // παραλείπεται ο κωδικός clientOut.close (); serverOut.close (); System.out.println ("Οι συνδέσεις έκλεισαν."); }}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step19
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step19

Βήμα 19. Τερματισμός διακομιστή

Οι συνδέσεις έχουν αποσυνδεθεί, αλλά ο διακομιστής εξακολουθεί να λειτουργεί. Οπως και

ServerSocket

δεν σχετίζεται με καμία ροή, πρέπει να κλείσει ρητά με κλήση

Κλείσε()

μέθοδος.

// παράλειψη κωδικού εισαγωγής java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); // ο κωδικός παραλείπεται System.out.println ("Η επικοινωνία είναι έτοιμη."); // παραλείπεται ο κωδικός clientOut.close (); serverOut.close (); System.out.println ("Οι συνδέσεις έκλεισαν."); server.close (); }}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step20
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step20

Βήμα 20. Τερματισμός διακομιστή καταγραφής

Για λόγους καταγραφής, η εκτύπωση στον διακομιστή κονσόλας έχει τερματιστεί.

// παράλειψη κωδικού εισαγωγής java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. Socket; public class NetworkAppExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; ServerSocket server = νέο ServerSocket (θύρα, 50, InetAddress.getByName (host)); System.out.println ("Ο διακομιστής ξεκίνησε."); Υπολογιστής υποδοχής = νέα υποδοχή (κεντρικός υπολογιστής, θύρα). System.out.println ("Σύνδεση με διακομιστή …"); Σύνδεση πρίζας = server.accept (); System.out.println ("Η σύνδεση πραγματοποιήθηκε."); // ο κωδικός παραλείπεται System.out.println ("Η επικοινωνία είναι έτοιμη."); // παραλείπεται ο κωδικός clientOut.close (); serverOut.close (); System.out.println ("Οι συνδέσεις έκλεισαν."); server.close (); System.out.println ("Ο διακομιστής τερματίστηκε."); }}

Δημιουργήστε μια εφαρμογή δικτύου στην Java Step21
Δημιουργήστε μια εφαρμογή δικτύου στην Java Step21

Βήμα 21. Μεταγλωττίστε και εκτελέστε

Η καταγραφή μας επέτρεψε να γνωρίζουμε εάν η εφαρμογή ήταν επιτυχής ή όχι. Αναμενόμενη έξοδος:

Ο διακομιστής ξεκίνησε. Σύνδεση με διακομιστή… Η σύνδεση πραγματοποιήθηκε. Η επικοινωνία είναι έτοιμη. Μήνυμα που στάλθηκε στον διακομιστή: Hello World Μήνυμα που ελήφθη από τον πελάτη: Hello World Connections έκλεισε. Ο διακομιστής τερματίστηκε.

Σε περίπτωση που η έξοδός σας δεν είναι όπως η παραπάνω, η οποία είναι απίθανο να συμβεί, υπάρχουν μερικές λύσεις:

  • Εάν η έξοδος σταματήσει στη γραμμή

    Η ΣΥΝΔΕΣΗ καθιερωθηκε.

    και χρησιμοποιούνται ρεύματα αντικειμένων, ξεπλύνετε το καθένα

    ObjectOutputStream

  • αμέσως μετά την προετοιμασία, επειδή οι κεφαλίδες, για κάποιο λόγο, δεν στάλθηκαν.
  • Εάν η έξοδος εκτυπωθεί

    java.net. BindException: Διεύθυνση που χρησιμοποιείται ήδη

  • επιλέξτε διαφορετικό αριθμό θύρας επειδή ο καθορισμένος χρησιμοποιείται ήδη.

Συμβουλές

  • Η σύνδεση σε διακομιστή σε διαφορετικό δίκτυο γίνεται μέσω σύνδεσης στην εξωτερική διεύθυνση IP μιας συσκευής που εκτελεί τον διακομιστή που διαθέτει προωθημένη θύρα.
  • Η σύνδεση σε διακομιστή στο ίδιο δίκτυο γίνεται είτε με σύνδεση στην ιδιωτική διεύθυνση IP μιας συσκευής που εκτελεί τον διακομιστή είτε με προώθηση μιας θύρας και σύνδεση με την εξωτερική διεύθυνση IP της συσκευής.
  • Υπάρχουν λογισμικά, όπως το Hamachi, που επιτρέπουν τη σύνδεση στον διακομιστή σε διαφορετικό δίκτυο χωρίς προώθηση θύρας, αλλά απαιτεί εγκατάσταση του λογισμικού και στις δύο συσκευές.

Παραδείγματα

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

Server.java

εισαγωγή java.io. IOException; εισαγωγή java.net. InetAddress; εισαγωγή java.net. ServerSocket; εισαγωγή java.net. SocketException; εισαγωγή java.net. UnknownHostException εισαγωγή java.util. ArrayList; εισαγωγή java.util. Collection; εισαγωγή java.util. List; /*** Η κλάση {@code Server} αντιπροσωπεύει ένα τελικό σημείο διακομιστή σε ένα δίκτυο. Ο {@κωδικός διακομιστής} μόλις συνδεθεί σε μια συγκεκριμένη διεύθυνση και θύρα IP *, δημιουργεί συνδέσεις με πελάτες και είναι σε θέση να επικοινωνεί μαζί τους ή να τους αποσυνδέει. *

* Αυτή η τάξη είναι ασφαλής για θέματα. * * @version 1.0 * @see Client * @see Connection */ public class Server υλοποιεί Runnable {private serverSocket server; ιδιωτική λίστα συνδέσεις? ιδιωτικό νήμα νήματος. ιδιωτικές τελικές συνδέσεις αντικειμένου Κλείδωμα = νέο αντικείμενο (); /** * Δημιουργεί έναν {@κωδικό διακομιστή} που αλληλεπιδρά με πελάτες στο καθορισμένο όνομα κεντρικού υπολογιστή και θύρα με το καθορισμένο * ζητούμενο μέγιστο μήκος μιας ουράς εισερχόμενων πελατών. * * @param host Διεύθυνση κεντρικού υπολογιστή για χρήση. * @param port Αριθμός θύρας για χρήση. * @param backlog Ζητήθηκε μέγιστο μήκος ουράς εισερχόμενων πελατών. * @throws NetworkException Εάν παρουσιαστεί σφάλμα κατά την εκκίνηση ενός διακομιστή. */ public Server (String host, int port, int backlog) ρίχνει NetworkException {try {server = new ServerSocket (port, backlog, InetAddress.getByName (host)); } catch (UnknownHostException e) {ρίξτε νέο NetworkException ("Δεν ήταν δυνατή η επίλυση του ονόματος κεντρικού υπολογιστή:" + host, e); } catch (IllegalArgumentException ε) {ρίξτε νέο NetworkException ("Ο αριθμός θύρας πρέπει να είναι μεταξύ 0 και 65535 (συμπεριλαμβανομένου):" + θύρα); } catch (IOException e) {ρίξτε νέο NetworkException ("Ο διακομιστής δεν μπόρεσε να ξεκινήσει.", ε); } συνδέσεις = Collections.synchronizedList (νέα ArrayList ()); νήμα = νέο νήμα (αυτό); thread.start (); } /*** Δημιουργεί έναν {@κωδικό διακομιστή} που αλληλεπιδρά με πελάτες στο καθορισμένο όνομα κεντρικού υπολογιστή και θύρα. * * @param host Διεύθυνση κεντρικού υπολογιστή για σύνδεση. * @param port Αριθμός θύρας για σύνδεση. * @throws NetworkException Εάν παρουσιαστούν σφάλματα κατά την εκκίνηση ενός διακομιστή. */ public Server (String host, int port) ρίχνει το NetworkException {αυτό (host, port, 50); } /*** Ακούει, αποδέχεται και καταγράφει εισερχόμενες συνδέσεις από πελάτες. */ @Override public void run () {while (! Server.isClosed ()) {try {connections.add (new Connection (server.accept ())); } catch (SocketException e) {if (! e.getMessage (). ισούται με ("Socket κλειστό")) {e.printStackTrace (); }} catch (NetworkException | IOException e) {e.printStackTrace (); }}} /*** Στέλνει δεδομένα σε όλους τους εγγεγραμμένους πελάτες. * * @param Δεδομένα για αποστολή. * @throws IllegalStateException Εάν επιχειρείται η εγγραφή δεδομένων όταν ο διακομιστής είναι εκτός σύνδεσης. * @throws IllegalArgumentException Εάν τα δεδομένα προς αποστολή είναι μηδενικά. */ public void broadcast (Object data) {if (server.isClosed ()) {ρίξτε νέο IllegalStateException ("Δε στέλνονται δεδομένα, ο διακομιστής είναι εκτός σύνδεσης."); } if (data == null) {throw new IllegalArgumentException ("null data"); } synchronized (connectionsLock) {for (Σύνδεση σύνδεσης: συνδέσεις) {try {connection.send (δεδομένα); System.out.println ("Τα δεδομένα αποστέλλονται με επιτυχία στον πελάτη."); } catch (NetworkException e) {e.printStackTrace (); }}}} /*** Στέλνει ένα μήνυμα αποσύνδεσης και αποσυνδέει τον καθορισμένο πελάτη. * * @param σύνδεση Πελάτης για αποσύνδεση. * @throws NetworkException Εάν παρουσιαστεί σφάλμα κατά το κλείσιμο της σύνδεσης. */ public void disconnect (Connection connection) ρίχνει NetworkException {if (connections.remove (connection)) {connection.close (); }} /*** Στέλνει ένα μήνυμα αποσύνδεσης σε όλους τους πελάτες, τους αποσυνδέει και τερματίζει τον διακομιστή. */ public void close () ρίχνει το NetworkException {synchronized (connectionsLock) {for (Connection connection: συνδέσεις) {try {connection.close (); } catch (NetworkException e) {e.printStackTrace (); }}} συνδέσεις.clear (); δοκιμάστε {server.close (); } catch (IOException e) {ρίξτε νέο NetworkException ("Σφάλμα κατά το κλείσιμο του διακομιστή."); } τέλος {thread.interrupt (); }} /*** Επιστρέφει αν ο διακομιστής είναι συνδεδεμένος ή όχι. * * @return True εάν ο διακομιστής είναι συνδεδεμένος. Falεύτικο, αλλιώς. */ public boolean isOnline () {return! server.isClosed (); } /*** Επιστρέφει μια σειρά εγγεγραμμένων πελατών. */ public Connection getConnections () {synchronized (connectionsLock) {return connections.toArray (new Connection [connections.size ()]); }}}

Client.java

εισαγωγή java.io. IOException; εισαγωγή java.net. Socket; εισαγωγή java.net. UnknownHostException /*** Η κλάση {@code Client} αντιπροσωπεύει ένα τελικό σημείο πελάτη σε ένα δίκτυο. Το {@code Client}, μόλις συνδεθεί σε έναν συγκεκριμένο διακομιστή *, είναι εγγυημένο ότι θα μπορεί να επικοινωνεί μόνο με τον διακομιστή. Το αν οι άλλοι πελάτες λαμβάνουν ή όχι τα δεδομένα * εξαρτάται από την υλοποίηση του διακομιστή. *

* Αυτή η τάξη είναι ασφαλής για θέματα. * * @version 1.0 * @see Server * @see Connection */ public class Client {private Connection connection; /*** Δημιουργεί ένα {@code Client} συνδεδεμένο στον διακομιστή στον καθορισμένο κεντρικό υπολογιστή και θύρα. * * @param host Διεύθυνση κεντρικού υπολογιστή για σύνδεση. * @param port Αριθμός θύρας για σύνδεση. * @throws NetworkException Εάν παρουσιαστεί σφάλμα κατά την εκκίνηση ενός διακομιστή. */ public Client (String host, int port) ρίχνει το NetworkException {try {connection = new Connection (new Socket (host, port)); } catch (UnknownHostException e) {ρίξτε νέο NetworkException ("Δεν ήταν δυνατή η επίλυση του ονόματος κεντρικού υπολογιστή:" + host, e); } catch (IllegalArgumentException ε) {ρίξτε νέο NetworkException ("Ο αριθμός θύρας πρέπει να είναι μεταξύ 0 και 65535 (συμπεριλαμβανομένου):" + θύρα); } catch (IOException e) {ρίξτε νέο NetworkException ("Ο διακομιστής δεν μπόρεσε να ξεκινήσει.", ε); }} /*** Στέλνει δεδομένα στο άλλο μέρος. * * @param Δεδομένα για αποστολή. * @throws NetworkException Εάν η εγγραφή στη ροή εξόδου αποτύχει. * @throws IllegalStateException Εάν επιχειρείται η εγγραφή δεδομένων όταν η σύνδεση είναι κλειστή. * @throws IllegalArgumentException Εάν τα δεδομένα προς αποστολή είναι μηδενικά. * @throws UnsupportedOperationException Εάν επιχειρείται αποστολή μη υποστηριζόμενου τύπου δεδομένων. */ public void send (Object data) ρίχνει NetworkException {connection.send (data); } /*** Στέλνει ένα μήνυμα αποσύνδεσης και κλείνει τη σύνδεση με το διακομιστή. */ public void close () ρίχνει το NetworkException {connection.close (); } /*** Επιστρέφει αν ο πελάτης είναι συνδεδεμένος ή όχι στον διακομιστή. * * @return True εάν ο πελάτης είναι συνδεδεμένος. Falεύτικο, αλλιώς. */ public boolean isOnline () {return connection.isConnected (); } /*** Επιστρέφει την παρουσία {@link Connection} του προγράμματος -πελάτη. */ public Connection getConnection () {επιστροφή σύνδεσης; }}

Connection.java

εισαγωγή java.io. DataInputStream; εισαγωγή java.io. DataOutputStream; εισαγωγή java.io. IOException; εισαγωγή java.net. Socket; εισαγωγή java.net. SocketException; /** * Η κλάση {@code Connection} αντιπροσωπεύει είτε σύνδεση από διακομιστή σε πελάτη είτε τελικό σημείο πελάτη σε δίκτυο * {@code Connection}, αφού συνδεθεί, είναι σε θέση να ανταλλάσσει δεδομένα με άλλα μέρη ή μέρη, ανάλογα σε διακομιστή * υλοποίηση. *

* Αυτή η τάξη είναι ασφαλής για θέματα. * * @version 1.0 * @see Server * @see Client */ public class Connection υλοποιεί Runnable {private socket socket; ιδιωτικό DataOutputStream out? ιδιωτικό DataInputStream σε? ιδιωτικό νήμα νήματος. ιδιωτικό τελικό αντικείμενο writeLock = νέο αντικείμενο (); ιδιωτικό τελικό αντικείμενο readLock = νέο αντικείμενο (); /*** Κατασκευάζει {@code Connection} χρησιμοποιώντας ροές μιας καθορισμένης {@link Socket}. * * @param socket Socket για ανάκτηση των ροών.*/ public Connection (Socket socket) ρίχνει το NetworkException {if (socket == null) {throw new IllegalArgumentException ("null socket"); } this.socket = πρίζα; δοκιμάστε {out = new DataOutputStream (socket.getOutputStream ()); } catch (IOException ε) {ρίξτε νέο NetworkException ("Δεν ήταν δυνατή η πρόσβαση στη ροή εξόδου.", ε); } try {in = new DataInputStream (socket.getInputStream ()); } catch (IOException ε) {ρίξτε νέο NetworkException ("Δεν ήταν δυνατή η πρόσβαση στη ροή εισόδου.", ε); } νήμα = νέο νήμα (αυτό); thread.start (); } /*** Διαβάζει μηνύματα ενώ η σύνδεση με το άλλο μέρος είναι ζωντανή. */ @Override public void run () {while (! Socket.isClosed ()) {try {int identifier; byte bytes; συγχρονισμένο (readLock) {αναγνωριστικό = in.readInt (); int μήκος = in.readInt (); if (μήκος> 0) {bytes = νέο byte [μήκος]; in.readFully (bytes, 0, bytes.length); } else {συνέχεια; }} switch (αναγνωριστικό) {case Identifier. INTERNAL: String command = new String (bytes); if (command.equals ("disconnect")) {if (! socket.isClosed ()) {System.out.println ("Πακέτο αποσύνδεσης ελήφθη."); δοκιμάστε {close ()? } catch (NetworkException e) {return; } } } Διακοπή; case Identifier. TEXT: System.out.println ("Το μήνυμα ελήφθη:" + νέα συμβολοσειρά (bytes)); Διακοπή; προεπιλογή: System.out.println ("Λήφθηκαν μη αναγνωρισμένα δεδομένα."); }} catch (SocketException e) {if (! e.getMessage (). ισούται με ("Socket κλειστή")) {e.printStackTrace (); }} catch (IOException e) {e.printStackTrace (); }}} /*** Στέλνει δεδομένα στο άλλο μέρος. * * @param Δεδομένα για αποστολή. * @throws NetworkException Εάν η εγγραφή στη ροή εξόδου αποτύχει. * @throws IllegalStateException Εάν επιχειρείται η εγγραφή δεδομένων όταν η σύνδεση είναι κλειστή. * @throws IllegalArgumentException Εάν τα δεδομένα προς αποστολή είναι μηδενικά. * @throws UnsupportedOperationException Εάν επιχειρείται αποστολή μη υποστηριζόμενου τύπου δεδομένων. */ public void send (Object data) ρίχνει NetworkException {if (socket.isClosed ()) {ρίξτε νέο IllegalStateException ("Δε στέλνονται δεδομένα, η σύνδεση είναι κλειστή."); } if (data == null) {throw new IllegalArgumentException ("null data"); } int αναγνωριστικό; byte bytes; if (data exampleof String) {identifier = Identifier. TEXT; bytes = ((String) data).getBytes (); } else {ρίξτε νέο UnsupportedOperationException ("Μη υποστηριζόμενος τύπος δεδομένων:" + data.getClass ()); } δοκιμάστε {synchronized (writeLock) {out.writeInt (αναγνωριστικό); out.writeInt (bytes.length); out.write (bytes); out.flush (); }} catch (IOException e) {ρίξτε νέο NetworkException ("Δεν ήταν δυνατή η αποστολή δεδομένων.", ε); }} /*** Στέλνει ένα μήνυμα αποσύνδεσης και κλείνει τη σύνδεση με το άλλο μέρος. */ public void close () ρίχνει NetworkException {if (socket.isClosed ()) {ρίξτε νέο IllegalStateException ("Η σύνδεση είναι ήδη κλειστή."); } δοκιμάστε {byte message = "disconnect".getBytes (); συγχρονισμένο (writeLock) {out.writeInt (Identifier. INTERNAL); out.writeInt (μήνυμα. μήκος); out.write (μήνυμα); out.flush (); }} catch (IOException e) {System.out.println ("Δεν ήταν δυνατή η αποστολή του μηνύματος αποσύνδεσης."); } δοκιμάστε {synchronized (writeLock) {out.close (); }} catch (IOException e) {ρίξτε νέο NetworkException ("Σφάλμα κατά το κλείσιμο της σύνδεσης.", ε); } τέλος {thread.interrupt (); }} /*** Επιστρέφει αν η σύνδεση με το άλλο μέρος είναι ζωντανή ή όχι. * * @return True αν η σύνδεση είναι ζωντανή. Falεύτικο, αλλιώς. */ public boolean isConnected () {return! socket.isClosed (); }}

Identifier.java

/** * Η κλάση {@code Identifier} περιέχει σταθερές που χρησιμοποιούνται από την {@link Connection} για σειριοποίηση και αποστείρωση των δεδομένων * που αποστέλλονται μέσω του δικτύου. * * @version 1.0 * @see Connection * / δημόσιο αναγνωριστικό τελικής κλάσης { / ** * Αναγνωριστικό για εσωτερικά μηνύματα. */ public static final int ΕΣΩΤΕΡΙΚΟ = 1; /*** Αναγνωριστικό για μηνύματα κειμένου. */ public static final int TEXT = 2; }

NetworkException.java

/*** Η κλάση {@code NetworkException} υποδεικνύει σφάλμα που σχετίζεται με το δίκτυο. * / public class NetworkException επεκτείνει την εξαίρεση { / *** Δημιουργεί ένα {@code NetworkException} με μήνυμα {@code null} ως μήνυμα. * / public NetworkException () {} / *** Δημιουργεί ένα {@code NetworkException} με το καθορισμένο μήνυμα. * * @param μήνυμα Ένα μήνυμα για την περιγραφή του σφάλματος. */ public NetworkException (Μήνυμα συμβολοσειράς) {super (μήνυμα); } /*** Δημιουργεί ένα {@code NetworkException} με το καθορισμένο μήνυμα και αιτία. * * @param μήνυμα Ένα μήνυμα για την περιγραφή του σφάλματος. * @param cause Αιτία σφάλματος. */ δημόσιο NetworkException (Μήνυμα συμβολοσειράς, Αιτία που μπορεί να πεταχτεί) {super (μήνυμα, αιτία); } /*** Δημιουργεί ένα {@code NetworkException} με την καθορισμένη αιτία. * * @param cause Αιτία σφάλματος. */ public NetworkException (Αιτία που μπορεί να πεταχτεί) {super (αιτία); }}

UsageExample.java

/*** Η κλάση {@code UsageExample} εμφανίζει τη χρήση των {@link Server} και {@link Client}. Αυτά τα παραδείγματα χρησιμοποιούν * {@link Thread#sleep (long)} για να διασφαλίσουν ότι κάθε τμήμα εκτελείται επειδή η γρήγορη εκκίνηση και κλείσιμο προκαλεί την μη εκτέλεση ορισμένων τμημάτων *. * * @version 1.0 * @see Server * @see Client */ public class UsageExample {public static void main (String args) ρίχνει Εξαίρεση {String host = "localhost"; θύρα int = 10430; Διακομιστής διακομιστή = νέος διακομιστής (κεντρικός υπολογιστής, θύρα). Πελάτης πελάτη = νέος Πελάτης (κεντρικός υπολογιστής, θύρα). Thread.sleep (100L); client.send ("Γεια."); server.broadcast ("Γεια σου, φίλε!"); Thread.sleep (100L); server.disconnect (server.getConnections () [0]); // ή client.close () για αποσύνδεση από τον διακομιστή από την πλευρά του πελάτη.close (); }}

Συνιστάται: