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

Java Advanced Key Knowledge Points-23-Προγραμματισμός δικτύου

2024-07-12

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

Εισαγωγή στον προγραμματισμό δικτύου

δομή λογισμικού

  • Δομή C/S: Το πλήρες όνομα είναι δομή πελάτη/διακομιστή, η οποία αναφέρεται στη δομή πελάτη και διακομιστή.
  • Δομή B/S: Το πλήρες όνομα είναι δομή προγράμματος περιήγησης/διακομιστή, η οποία αναφέρεται στη δομή του προγράμματος περιήγησης και του διακομιστή.

Πρωτόκολλο επικοινωνίας δικτύου

网络通信协议:通信协议是对计算机必须遵守的规则,只有遵守这些规则,计算机之间才能进行通信。

  • Πρωτόκολλο TCP/IP: Πρωτόκολλο ελέγχου μετάδοσης/πρωτόκολλο Διαδικτύου (πρωτόκολλο ελέγχου μετάδοσης/πρωτόκολλο Διαδικτύου), είναι
    Το πιο βασικό και διαδεδομένο πρωτόκολλο του Διαδικτύου.
    Εισαγάγετε την περιγραφή της εικόνας εδώ

Ταξινόμηση πρωτοκόλλου

java.net 包中提供了两种常见的网络协议的支持

  1. TCP: Πρωτόκολλο ελέγχου μετάδοσης. Το πρωτόκολλο TCP είναι ένα πρωτόκολλο επικοινωνίας προσανατολισμένο στη σύνδεση, δηλαδή, πριν από τη μετάδοση δεδομένων, δημιουργείται μια λογική σύνδεση μεταξύ του άκρου αποστολής και του άκρου λήψης και στη συνέχεια τα δεδομένα μεταδίδονται μεταξύ δύο Υπολογιστές.
  2. UDP: Πρωτόκολλο User Datagram. Το πρωτόκολλο UDP είναι πρωτόκολλο χωρίς σύνδεση. Κατά τη μετάδοση δεδομένων, δεν χρειάζεται να δημιουργηθεί σύνδεση Ανεξάρτητα από το αν έχει ξεκινήσει η υπηρεσία του άλλου μέρους, τα δεδομένα, η πηγή δεδομένων και ο προορισμός ενσωματώνονται απευθείας στο πακέτο δεδομένων και αποστέλλονται απευθείας. Το μέγεθος κάθε πακέτου περιορίζεται στα 64k. Είναι αναξιόπιστο πρωτόκολλο γιατί δεν υπάρχει σύνδεση, επομένως η ταχύτητα μετάδοσης είναι γρήγορη, αλλά τα δεδομένα χάνονται εύκολα.

Τριμερής χειραψία στο TCP: Στο πρωτόκολλο TCP, στο στάδιο προετοιμασίας της αποστολής δεδομένων, υπάρχουν τρεις αλληλεπιδράσεις μεταξύ του πελάτη και του διακομιστή για να διασφαλιστεί η αξιοπιστία της σύνδεσης.

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

Τρία στοιχεία προγραμματισμού δικτύου

  1. Πρωτόκολλο: Οι κανόνες που πρέπει να τηρούν οι επικοινωνίες δικτύου υπολογιστών
  2. Διεύθυνση IP: αναφέρεται στη Διεύθυνση Πρωτοκόλλου Διαδικτύου, κοινώς γνωστή ως IP. Οι διευθύνσεις IP χρησιμοποιούνται για τον μοναδικό αριθμό υπολογιστών σε ένα δίκτυο.
  • IPv4: Είναι ένας δυαδικός αριθμός 32 bit, που συνήθως χωρίζεται σε 4 byte, εκφρασμένος με τη μορφή abcd, όπως 192.168.65.100. Μεταξύ αυτών, τα a, b, c και d είναι όλοι δεκαδικοί ακέραιοι μεταξύ 0 και 255, επομένως μπορούν να αναπαρασταθούν έως και 4,2 δισεκατομμύρια.
  • Χρησιμοποιώντας ένα μήκος διεύθυνσης 128-bit, κάθε ομάδα 16 byte χωρίζεται σε 8 ομάδες δεκαεξαδικών αριθμών, που εκφράζονται ως ABCD:EF01:2345:6789:ABCD:EF01:2345:6789, γεγονός που επιλύει το πρόβλημα των ανεπαρκών πόρων διεύθυνσης δικτύου .
    Εντολές που χρησιμοποιούνται συνήθως:
  • ipconfig [Προβολή της τοπικής διεύθυνσης IP]
    Εισαγάγετε την περιγραφή της εικόνας εδώ
  • Πραγματοποιήστε ping στη διεύθυνση IP του space [ελέγξτε εάν το δίκτυο είναι συνδεδεμένο]
  1. Ο αριθμός θύρας
  • Ένας ακέραιος αριθμός που αντιπροσωπεύεται από δύο byte, το εύρος τιμών του είναι 0 ~ 65535.Μεταξύ αυτών, οι αριθμοί θυρών μεταξύ 0 και 1023 χρησιμοποιούνται από ορισμένα γνωστά δίκτυα
    Υπηρεσίες δικτύου και εφαρμογές, οι συνηθισμένες εφαρμογές πρέπει να χρησιμοποιούν αριθμούς θύρας άνω του 1024. Εάν ο αριθμός θύρας καταλαμβάνεται από άλλη υπηρεσία ή εφαρμογή, το τρέχον πρόγραμμα θα αποτύχει να ξεκινήσει.
    Προσδιορίστε τις διαδικασίες στο δίκτυο: 协议 + IP地址 + 端口号

Το πρόγραμμα επικοινωνίας TCP

TCP通信能实现两台计算机之间的数据交互,通信的两端,要严格区分为客户端(Client)与服务端(Server)。

Βήματα επικοινωνίας

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

Στην Java, παρέχονται δύο κλάσεις για την υλοποίηση προγραμμάτων επικοινωνίας TCP:

  1. Πελάτης: Αντιπροσωπεύεται από την κλάση java.net.Socket. Δημιουργήστε ένα αντικείμενο Socket, στείλτε ένα αίτημα σύνδεσης στον διακομιστή, ο διακομιστής ανταποκρίνεται στο αίτημα και οι δύο δημιουργούν μια σύνδεση και ξεκινούν την επικοινωνία.
  2. Διακομιστής: αντιπροσωπεύεται από την κλάση java.net.ServerSocket. Η δημιουργία ενός αντικειμένου ServerSocket ισοδυναμεί με την εκκίνηση μιας υπηρεσίας και την αναμονή της σύνδεσης του πελάτη.

Κατηγορία πρίζας

Socket 类:该类实现客户端套接字,套接字指的是两台设备之间通讯的端点。
Μέθοδος κατασκευής:
public Socket(String host, int port) :Δημιουργεί ένα αντικείμενο υποδοχής και το συνδέει με τον καθορισμένο αριθμό θύρας στον καθορισμένο κεντρικό υπολογιστή. Εάν ο καθορισμένος κεντρικός υπολογιστής είναι μηδενικός, ισοδυναμεί με την καθορισμένη διεύθυνση που είναι η διεύθυνση βρόχου (Η διεύθυνση loopback (127.xxx) είναι η τοπική διεύθυνση επαναφοράς (Loopback Address))。
Μέθοδοι μελών:

  • public InputStream getInputStream() : Επιστρέφει τη ροή εισόδου για αυτήν την υποδοχή.
  • public OutputStream getOutputStream() : Επιστρέφει τη ροή εξόδου για αυτήν την υποδοχή.
  • public void close() : Κλείστε αυτήν την πρίζα.
  • public void shutdownOutput() : Απενεργοποιεί τη ροή εξόδου για αυτήν την υποδοχή.

Κλάση ServerSocket

ServerSocket 类:这个类实现了服务器套接字,该对象等待通过网络的请求。
Μέθοδος κατασκευής:
public ServerSocket(int port): Χρησιμοποιήστε αυτόν τον κατασκευαστή για να τον συνδέσετε σε έναν δείκτη κατά τη δημιουργία ενός αντικειμένου ServerSocket.
Σε έναν συγκεκριμένο αριθμό θύρας, η θύρα παραμέτρου είναι ο αριθμός θύρας.
Μέθοδοι μελών:
public Socket accept() : Ακούστε και αποδεχτείτε συνδέσεις και επιστρέψτε ένα νέο αντικείμενο Socket για επικοινωνία με τον πελάτη.αυτή τη μέθοδο
Θα αποκλειστεί μέχρι να δημιουργηθεί η σύνδεση.

Απλό πρόγραμμα δικτύου TCP

Ανάλυση επικοινωνίας TCP:

  1. [Server] Ξεκινήστε, δημιουργήστε αντικείμενο ServerSocket και περιμένετε για σύνδεση.
  2. [Πελάτης] Ξεκινήστε, δημιουργήστε αντικείμενο Socket και ζητήστε σύνδεση.
  3. Ο [Διακομιστής] λαμβάνει τη σύνδεση, καλεί τη μέθοδο αποδοχής και επιστρέφει ένα αντικείμενο Socket.
  4. Αντικείμενο [Client] Socket, λαμβάνει OutputStream και εγγράφει δεδομένα στον διακομιστή.
  5. Αντικείμενο Socket [Server], λαμβάνει το InputStream και διαβάζει τα δεδομένα που αποστέλλονται από τον πελάτη.
  6. Αντικείμενο Socket [Διακομιστής], αποκτά OutputStream και γράφει δεδομένα πίσω στον πελάτη.
  7. [Πελάτης] Το αντικείμενο Scoket, λαμβάνει το InputStream, αναλύει και εγγράφει δεδομένα.
  8. [Πελάτης] Αποδεσμεύστε πόρους και αποσυνδέστε.

Παράδειγμα κώδικα:

  • Service-Terminal:
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerTCP {
    public static void main(String[] args) throws IOException {
        System.out.println("服务端启动 , 等待连接 .... ");
        // 1.创建 ServerSocket对象,绑定端口,开始等待连接
        ServerSocket ss = new ServerSocket(6666);
        // 2.接收连接 accept 方法, 返回 socket 对象.
        Socket server = ss.accept();
        // 3.通过socket 获取输入流
        InputStream is = server.getInputStream();
        // 4.一次性读取数据
        // 4.1 创建字节数组
        byte[] b = new byte[1024];
        // 4.2 据读取到字节数组中.
        int len = is.read(b);
        // 4.3 解析数组,打印字符串信息
        String msg = new String(b, 0, len);
        System.out.println(msg);
        //5.关闭资源.
        is.close();
        server.close();
    }
}
  • 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

Ο διακομιστής καθορίζει τον αριθμό θύρας, λαμβάνει το αντικείμενο Socket μέσω της μεθόδου accept(), λαμβάνει τη ροή εισόδου μέσω του αντικειμένου πελάτη και, τέλος, διαβάζει τα δεδομένα και περιμένει το μήνυμα που αποστέλλεται από τον πελάτη.

  • πελάτης
import java.net.Socket;

public class ClientTCP {
    public static void main(String[] args) throws Exception {
        System.out.println("客户端 发送数据");
        // 1.创建 Socket ( ip , port ) , 确定连接到哪里.
        Socket client = new Socket("localhost", 6666);
        // 2.获取流对象 . 输出流
        OutputStream os = client.getOutputStream();
        // 3.写出数据.
        os.write("你好么? tcp ,我来了".getBytes());
        // 4. 关闭资源 .
        os.close();
        client.close();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

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

Μεταφόρτωση αρχείου [Εκτεταμένη]

  1. [Client] Ροή εισόδου, ανάγνωση δεδομένων αρχείου από τον σκληρό δίσκο στο πρόγραμμα.
  2. [Πελάτης] Ροή εξόδου, εγγραφή δεδομένων αρχείου στο διακομιστή.
  3. [Διακομιστής] Ροή εισόδου, ανάγνωση δεδομένων αρχείου στο πρόγραμμα διακομιστή.
  4. [Διακομιστής] Ροή εξόδου, εγγραφή δεδομένων αρχείου στον σκληρό δίσκο του διακομιστή.
  5. [Διακομιστής] Λάβετε τη ροή εξόδου και γράψτε πίσω τα δεδομένα.
  6. [Πελάτης] Λάβετε τη ροή εισόδου και αναλύστε και γράψτε τα δεδομένα.

数据准备:Τοποθετήστε ένα αρχείο με το όνομα test.jpg κάτω από τη μονάδα δίσκου D και δημιουργήστε έναν δοκιμαστικό φάκελο

Παράδειγμα κώδικα:

  • Υπηρέτης
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class FileUpload_Server {
    public static void main(String[] args) throws IOException {
        System.out.println("服务器 启动..... ");
        // 1. 创建服务端ServerSocket
        ServerSocket serverSocket = new ServerSocket(6666);
        // 2. 循环接收,建立连接
        while (true) {
        Socket accept = serverSocket.accept();
            /* 3. socket对象交给子线程处理,进行读写操作Runnable接口中,只有一个run方法,使用lambda表达式简化格式 */
            new Thread(() -> {
                try (   //3.1 获取输入流对象
                        BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
                        //3.2 创建输出流对象, 保存到本地 .
                        FileOutputStream fis = new FileOutputStream("D:/test/" + System.currentTimeMillis() + ".jpg");
                        BufferedOutputStream bos = new BufferedOutputStream(fis)) {
                    // 3.3 读写数据
                    byte[] b = new byte[1024 * 8];
                    int len;
                    while ((len = bis.read(b)) != -1) {
                        bos.write(b, 0, len);
                    }

                    // 4.=======信息回写===========================
                    System.out.println("back ........");
                    OutputStream out = accept.getOutputStream();
                    out.write("上传成功".getBytes());
                    out.close();

                    //5. 关闭 资源
                    bos.close();
                    bis.close();
                    accept.close();
                    System.out.println("文件上传已保存");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).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
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

Εδώ δημιουργούμε πρώτα ένα αντικείμενο διακομιστή, χρησιμοποιούμε το while(true) για να διασφαλίσουμε τη συνεχή σύνδεση με τον διακομιστή και, στη συνέχεια, ξεκινάμε ένα νήμα για να διασφαλίσουμε ότι όταν ένας χρήστης ανεβάζει ένα μεγάλο αρχείο, η αποτελεσματικότητα των άλλων χρηστών που ανεβάζουν αρχεία δεν θα επηρεαστεί. Χρησιμοποιήστε τα χιλιοστά του δευτερολέπτου συστήματος + '.jpg' για να ορίσετε το όνομα του αρχείου για να διασφαλίσετε ότι το όνομα του αρχείου δεν θα αντικατασταθεί λόγω του ίδιου ονόματος αρχείου κατά τη μεταφόρτωση.

  • πελάτης
import java.io.*;
import java.net.Socket;

public class FileUpload_Client {
    public static void main(String[] args) throws IOException {
        // 1.创建流对象
        // 1.1 创建输入流,读取本地文件
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\test.jpg"));
        // 1.2 创建输出流,写到服务端
        Socket socket = new Socket("localhost", 6666);
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        //2.写出数据.
        byte[] b = new byte[1024 * 8 ];
        int len ;
        while (( len = bis.read(b))!=-1) {
            bos.write(b, 0, len);
        }
        // 关闭输出流,通知服务端,写出数据完毕
        socket.shutdownOutput();
        System.out.println("文件发送完毕");   
        // 3. =====解析回写============
        InputStream in = socket.getInputStream();
        byte[] back = new byte[20];
        in.read(back);
        System.out.println(new String(back));
        in.close();
        // ============================
        // 4.释放资源
        socket.close();
        bis.close();
    }
}
  • 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

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

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