Κοινή χρήση τεχνολογίας

【JavaEE】Προγραμματισμός δικτύου——UDP

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Εισαγάγετε την περιγραφή της εικόνας εδώ
🤡🤡🤡个人主页🤡🤡🤡
🤡🤡🤡JavaEE专栏🤡🤡🤡

1. Υποδοχή Datagram (UDP)

1.1 Χαρακτηριστικά

  1. Χωρίς σύνδεση: Δεν χρειάζεται να δημιουργηθεί ένα ειδικό κανάλι πριν από τη μετάδοση των δεδομένων Κάθε πακέτο δεδομένων αποστέλλεται ανεξάρτητα και επιλέγει τη δική του διαδρομή για να φτάσει στον προορισμό πρέπει να το λάβετε.
  2. Αναξιόπιστη μετάδοση: Κατά τη μετάδοση δεδομένων, δεν χρειάζεται να προσέχετε εάν τα έχει λάβει το άλλο μέρος, απλώς στείλτε τα.
  3. Προσανατολισμός στη ροή δεδομένων: Η βασική μονάδα μετάδοσης δεδομένων είναι κάθε πρόγραμμα δεδομένων UDP Μετά την ανάγνωση και εγγραφή, μπορεί να διαβαστεί και να γραφτεί μόνο ένα πλήρες πρόγραμμα δεδομένων UDP.
  4. Full-duplex: Η αμφίδρομη επικοινωνία είναι δυνατή σε μία σύνδεση.

1.2 Κωδικοποίηση

Τα API Socket παρέχονται όλα από το σύστημα Τα API που παρέχονται από διαφορετικά συστήματα είναι διαφορετικά, αλλά αυτά τα API συστήματος ενσωματώνονται περαιτέρω σε Java.
Το socket api στο UDP εστιάζει σε δύο κατηγορίες: DatagramSocket και DatagramPacket

1.2.1 DatagramSocket

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

1.2.2 Πακέτο δεδομένων

Αυτή η κλάση περιγράφει τα datagrams UDP Ένα αντικείμενο DatagramPacket είναι ισοδύναμο με ένα UDP datagram.

1.2.3 Εφαρμογή διακομιστή ηχούς UDP (24*7).

Echo: Ο πελάτης στέλνει διαφορετικά αιτήματα στον διακομιστή και ο διακομιστής επιστρέφει διαφορετικές απαντήσεις. Αλλά η ηχώ εδώ είναι αυτό που ζητά ο πελάτης στον διακομιστή και ο διακομιστής ανταποκρίνεται χωρίς κανέναν υπολογισμό ή επιχειρηματική λογική.

public class udpEchoServer {
    public DatagramSocket socket = null;
    public udpEchoServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
    }
    public void  start() throws IOException {
        System.out.println("服务器启动!!!");
        while (true) {
            //接受客户端请求
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(requestPacket);
            //为了更好处理数据并方便打印,将接受的数据转化为字符串操作
            String request = new String(requestPacket.getData(),0,requestPacket.getLength());
            //处理客户端的请求(算术计算或者业务逻辑)
            String response = this.process(request);
            //将处理完的请求返还给客户端
            DatagramPacket resposePacket = new DatagramPacket(response.getBytes(),0,response.getBytes().length,
                    requestPacket.getSocketAddress());
            socket.send(resposePacket);
            //打印客户端的ip地址端口号和接收客户端的数据以及处理完客户端后的数据
            System.out.printf("[%s:%d] req = %s,resp = %sn",requestPacket.getAddress(),requestPacket.getPort(),
                    request,response);
        }
    }
    public String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        udpEchoServer udpEchoServer = new udpEchoServer(9999);
        udpEchoServer.start();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

Εισαγάγετε την περιγραφή της εικόνας εδώ
Το αντικείμενο DatagramPacket αντιπροσωπεύει ένα datagram Ένα UDP αποτελείται από μια κεφαλίδα και ένα ωφέλιμο φορτίο Η διεύθυνση IP και ο αριθμός θύρας στην κεφαλίδα είναι χαρακτηριστικά της κλάσης DatagramPacket, επομένως ο προγραμματιστής πρέπει να το κάνει. Με την προϋπόθεση, ακριβώς όπως ένας μοναχός που ζητά ελεημοσύνη, θα πρέπει να παρέχετε ένα μπολ για ελεημοσύνη, και στη συνέχεια κάθε οικογένεια βάζει φαγητό στο μπολ, καθώς η ουσία του datagram είναι δυαδικά δεδομένα, παρέχω έναν πίνακα byte ως ωφέλιμο φορτίο Αποθήκευση δεδομένων.
Εισαγάγετε την περιγραφή της εικόνας εδώ
Τα δεδομένα που λαμβάνονται από τον πελάτη πρέπει να επιστραφούν στον υπολογιστή-πελάτη αφού υποβληθούν σε επεξεργασία από τον διακομιστή, επομένως πρέπει να δημιουργηθεί ένα αντικείμενο DatagramPacket για να αποθηκεύσει τα δεδομένα που επεξεργάζεται ο διακομιστής και, στη συνέχεια, ο διακομιστής τα στέλνει στον πελάτη. Αυτή τη στιγμή, το αντικείμενο DatagramPacket δεν χρειάζεται να παρέχει κενό χώρο καταγράφονται κατά την αποστολή του στον πελάτη Πρέπει να λάβετε τη διεύθυνση IP και τον αριθμό θύρας του πελάτη μέσω του requestPacket.getSocketAddress().
Εισαγάγετε την περιγραφή της εικόνας εδώ
Δεδομένου ότι ο διακομιστής είναι σταθερός, μπορείτε να ορίσετε μόνοι σας τον αριθμό θύρας Ο αριθμός θύρας δημιουργείται κατά την εκκίνηση του διακομιστή.
Γιατί χρειάζομαι μια διεύθυνση IP με αριθμό θύρας;
Για να επιτευχθεί επιτυχής επικοινωνία μεταξύ των δύο μερών, πρέπει να υπάρχουν αυτοί οι τέσσερις βασικοί δείκτες:
Θύρα προέλευσης, IP προέλευσης, θύρα προορισμού, IP προορισμού
Μέσω αυτών των τεσσάρων βασικών δεικτών, μπορεί να επιτευχθεί η δικτυακή επικοινωνία μεταξύ των δύο μερών Δεν υπάρχει διεύθυνση IP του διακομιστή εδώ, επειδή ο πελάτης και ο διακομιστής βρίσκονται στον ίδιο κεντρικό υπολογιστή. Μπορούμε να χρησιμοποιήσουμε μια IP για να αναπαραστήσουμε το 172.0.0.1, επίσης γνωστό ως loopback IP.

1.2.4 Εφαρμογή πελάτη UDP

public class udpEchoClient {
    private DatagramSocket socket = null;
    private String serverIp;
    private int serverProt;
    public  udpEchoClient(String serverIp, int serverProt) throws SocketException {
        socket = new DatagramSocket();
        this.serverIp = serverIp;
        this.serverProt = serverProt;
    }
    public void start() throws IOException {
        System.out.println("客户端启动!");
        //1.从控制台获取字符串
        Scanner scanner = new Scanner(System.in);
        while(true) {
            System.out.println("请输入要发送的请求: ");
            String request = scanner.nextLine();
            //2.将输入的字符串发送给服务器,还要将发送的目标确定,IP和端口号
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), 0, request.getBytes().length,
                    InetAddress.getByName(serverIp), serverProt);
            socket.send(requestPacket);
            //3.从服务器读取到经过处理的响应
            DatagramPacket responsePackt = new DatagramPacket(new byte[4096], 4096);
            socket.receive(responsePackt);
            //将响应打印在控制台
            String response = new String(responsePackt.getData(), 0, responsePackt.getLength());
            System.out.println(response);
        }
    }
    public static void main(String[] args) throws IOException {
        udpEchoClient udpEchoClient = new udpEchoClient("127.0.0.1",9999);
        udpEchoClient.start();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

Εισαγάγετε την περιγραφή της εικόνας εδώ
Για τη συμβολοσειρά που λαμβάνεται από την κονσόλα, το αντικείμενο requestPacket λαμβάνει την αναφορά και το μήκος του αντικειμένου συμβολοσειράς, καθώς και τη δική του IP και Prot, και στη συνέχεια τη στέλνει στον διακομιστή μέσω της μεθόδου αποστολής της υποδοχής.
Εισαγάγετε την περιγραφή της εικόνας εδώ
Για να λάβετε μια απάντηση από τον διακομιστή, πρέπει να δημιουργήσετε ένα αντικείμενο answerPackt και να δημιουργήσετε έναν κενό πίνακα byte εκ των προτέρων για να λάβετε την απάντηση που λαμβάνεται από τον διακομιστή.
Διακρίνετε μερικές μεθόδους:
Πριν διακρίνουμε τις μεθόδους, πρέπει να κατανοήσουμε τις έννοιες των byte, των χαρακτήρων και των μορφών κωδικοποίησης
Τα byte και οι χαρακτήρες είναι ουσιαστικά δυαδικά, δηλαδή δεδομένα όπως το 0101, επειδή ο υπολογιστής αναγνωρίζει μόνο το 0101.
Byte: Το byte είναι η βασική μονάδα αποθήκευσης δεδομένων στον υπολογιστή. Το 1 byte είναι 8 bit, που σημαίνει ότι ένα byte μπορεί να αντιπροσωπεύει 256 διαφορετικές τιμές.
Χαρακτήρας: Ο χαρακτήρας είναι η βασική μονάδα για την αναπαράσταση πληροφοριών κειμένου Μεταφορά δεδομένων και αποθήκευση δεδομένων.
Φόρμα κωδικοποίησης:

  1. Κωδικός ASCII: χρησιμοποιείται για την αναπαράσταση αγγλικών χαρακτήρων.Χρησιμοποιεί 7 bit για να αναπαραστήσει 128 χαρακτήρες (συμπεριλαμβανομένων κεφαλαίων και πεζών γραμμάτων, αριθμών, σημείων στίξης και ορισμένων χαρακτήρων ελέγχου), αλλά δεν υποστηρίζει κινεζικούς χαρακτήρες Εδώ, ένας χαρακτήρας αντιστοιχεί σε ένα byte
  2. Unicode (UTF8): Το UTF-8 είναι μια φόρμα κωδικοποίησης μεταβλητού μήκους που περιλαμβάνει χαρακτήρες από όλα τα συστήματα γραφής σε όλο τον κόσμο. Είναι συμβατό με το σύνολο χαρακτήρων ASCII και υποστηρίζει χαρακτήρες από όλα τα συστήματα γραφής σε όλο τον κόσμο χαρακτήρας αντιστοιχεί σε 1-4 χαρακτήρες.
  3. GBK: χρησιμοποιεί κωδικοποίηση μεταβλητού μήκους, που χρησιμοποιείται κυρίως για κωδικοποίηση κινεζικών χαρακτήρων, ένας χαρακτήρας αντιστοιχεί σε 1-2 byte

Οι μέθοδοι είναι διαφορετικές:

  1. getBytes(): Λάβετε μια αναφορά στον πίνακα byte Το αντικείμενο είναι ένας χαρακτήρας Εδώ, οι χαρακτήρες μετατρέπονται σε byte για την αποθήκευση των δεδομένων.
  2. getBytes().length: Λάβετε το μήκος του πίνακα byte, το αντικείμενο είναι χαρακτήρας
  3. getData(): Αυτό που λαμβάνεται είναι μια αναφορά σε μια συμβολοσειρά που αποτελείται από χαρακτήρες. Εδώ, τα byte μετατρέπονται σε χαρακτήρες.
  4. getLength(): Το μήκος της συμβολοσειράς που λαμβάνεται, το αντικείμενο είναι byte
  5. getAddress(): Λάβετε τη διεύθυνση IP, το αντικείμενο είναι DatagramPacket
  6. getPort(): Λάβετε τον αριθμό θύρας Prot, το αντικείμενο είναι DatagramPacket
  7. getSocketAddress(): Λάβετε τη διεύθυνση IP και τον αριθμό θύρας Prot, το αντικείμενο είναι DatagramPacket
  8. InetAddress.getByName(): Αυτή η μέθοδος μπορεί να αναλύσει το όνομα του κεντρικού υπολογιστή και να επιστρέψει τη διεύθυνση IP του ονόματος κεντρικού υπολογιστή ή να επιστρέψει απευθείας το αντικείμενο InetAddress της δεδομένης διεύθυνσης IP Το ληφθέν αντικείμενο InetAddress μεταβιβάζεται στον διακομιστή και ο διακομιστής μπορεί να επιλύσει την IP λαμβάνοντας αυτό το αντικείμενο.

1.2.5 Εφαρμογή διακομιστή μετάφρασης λεξικού UDP

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

public class udpDictServer extends udpEchoServer{
    HashMap<String,String> map = null;
    public udpDictServer(int port) throws SocketException {
        super(port);
        map = new HashMap<>();
        map.put("server","服务");
        map.put("client","客户端");
        map.put("cat","🐱");
        map.put("dog","🐕");
        map.put("pig","🐖");
    }
    @Override
    public String process(String request) {
        return map.getOrDefault(request, "该词汇没有查询到");
    }

    public static void main(String[] args) throws IOException {
        udpDictServer udpDictServer = new udpDictServer(9999);
        udpDictServer.start();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

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

2. Διαδικασία πελάτη και διακομιστή

  1. Λάβετε δεδομένα από την κονσόλα
  2. Ο πελάτης στέλνει δεδομένα στον διακομιστή
  3. Ο διακομιστής λαμβάνει τα δεδομένα που αποστέλλονται από τον πελάτη
  4. Υπολογίστε την απόκριση
  5. Ο διακομιστής στέλνει την υπολογισμένη απόκριση στον πελάτη
  6. Ο πελάτης λαμβάνει την απάντηση που αποστέλλεται από τον διακομιστή
  7. Εκτυπώνει την απάντηση που αποστέλλεται από τον διακομιστή που λαμβάνεται από τον πελάτη στην κονσόλα