Berbagi teknologi

【JavaEE】 Pemrograman Jaringan —— UDP

2024-07-12

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

Masukkan deskripsi gambar di sini
🤡🤡🤡个人主页🤡🤡🤡
🤡🤡🤡JavaEE专栏🤡🤡🤡

1. Soket datagram (UDP)

1.1 Fitur

  1. Tanpa koneksi: Tidak perlu membuat saluran khusus sebelum data dikirim. Setiap paket data dikirim secara independen dan memilih jalurnya sendiri untuk mencapai tujuan perlu menerimanya.
  2. Transmisi tidak dapat diandalkan: Saat mengirimkan data, Anda tidak perlu memperhatikan apakah pihak lain telah menerimanya, kirimkan saja.
  3. Berorientasi pada aliran data: Unit dasar transmisi data adalah setiap datagram UDP. Setelah membaca dan menulis, hanya satu datagram UDP lengkap yang dapat dibaca dan ditulis.
  4. Full-duplex: Komunikasi dua arah dimungkinkan pada satu link.

1.2 Pengkodean

Semua API Socket disediakan oleh sistem. API yang disediakan oleh sistem yang berbeda berbeda-beda, tetapi API sistem ini diringkas lebih lanjut dalam Java.
Socket api di UDP berfokus pada dua kelas: DatagramSocket dan DatagramPacket

1.2.1 Soket Datagram

Fungsi kelas ini dapat dikatakan sebagai remote control untuk “mengoperasikan kartu jaringan”, yaitu operasi membaca dan menulis pada kartu jaringan, yang dapat dipahami sebagai membaca dan menulis seperti file.
Beberapa metode disediakan:
Masukkan deskripsi gambar di sini

1.2.2 Paket Datagram

Kelas ini menjelaskan datagram UDP. Objek DatagramPacket setara dengan datagram UDP. Setelah dikirim dan diterima, objek DatagramPacket dikirimkan.

1.2.3 Mengimplementasikan server gema UDP (24*7).

Gema: Klien mengirimkan permintaan berbeda ke server, dan server mengembalikan respons berbeda. Tapi gema di sini adalah apa yang diminta klien ke server, dan server merespons tanpa perhitungan atau logika bisnis apa pun.

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

Masukkan deskripsi gambar di sini
Objek DatagramPacket mewakili datagram. Datagram UDP terdiri dari header dan payload. Alamat IP dan nomor port di header adalah atribut dari kelas DatagramPacket, tetapi kelas payload tidak disediakan, jadi pemrogram perlu melakukannya. Disediakan sendiri, jadi seperti seorang biksu yang meminta sedekah, Anda perlu menyediakan mangkuk untuk sedekah, dan kemudian setiap keluarga memasukkan makanan ke dalam mangkuk tersebut. Karena inti dari datagram adalah data biner, saya menyediakan array byte sebagai muatannya . Menyimpan data.
Masukkan deskripsi gambar di sini
Data yang diterima dari klien harus dikembalikan ke klien setelah diproses oleh server, sehingga perlu dibuat objek DatagramPacket untuk menyimpan data yang diproses oleh server, kemudian server mengirimkannya ke klien. Saat ini objek DatagramPacket tidak perlu menyediakan ruang kosong, cukup masukkan data yang telah diproses ke dalam objek ini Karena alamat IP klien dan nomor port dicatat saat menerima data, hanya alamat IP dan nomor port klien dicatat saat mengirimkannya ke klien. Anda perlu mendapatkan alamat IP dan nomor port klien melalui requestPacket.getSocketAddress().
Masukkan deskripsi gambar di sini
Karena servernya tetap, Anda dapat langsung mengatur sendiri nomor portnya. Nomor port tersebut dibuat saat server dimulai.
Mengapa saya memerlukan alamat IP nomor port?
Untuk mencapai keberhasilan komunikasi antara kedua pihak, empat indikator inti berikut harus ada:
Port sumber, IP sumber, port tujuan, IP tujuan
Melalui keempat indikator inti ini, komunikasi jaringan antara kedua pihak dapat tercapai. Tidak ada alamat IP server di sini karena klien dan server berada di host yang sama. Kita dapat menggunakan IP untuk mewakili 172.0.0.1, juga dikenal sebagai IP loopback.

1.2.4 Mengimplementasikan klien 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

Masukkan deskripsi gambar di sini
Untuk string yang diterima dari konsol, objek requestPacket memperoleh referensi dan panjang objek string, serta IP dan Protnya sendiri, dan kemudian mengirimkannya ke server melalui metode kirim soket.
Masukkan deskripsi gambar di sini
Untuk menerima respon dari server, Anda perlu membuat objek responPackt dan membuat array byte kosong terlebih dahulu untuk menerima respon yang diterima dari server.
Bedakan beberapa metode:
Sebelum membedakan metode, kita perlu memahami konsep byte, karakter, dan bentuk pengkodean
Byte dan karakter pada dasarnya adalah biner, yaitu data seperti 0101, karena komputer hanya mengenali 0101.
Byte: Byte adalah unit dasar untuk penyimpanan data komputer. 1 byte adalah 8 bit. Setiap bit bisa bernilai 0 atau 1, artinya satu byte dapat mewakili 256 nilai berbeda.
Karakter: Karakter adalah unit dasar untuk mewakili informasi teks. Menurut bentuk pengkodean yang berbeda, jumlah byte yang sesuai dengan karakter bervariasi. Melalui bentuk pengkodean, karakter dapat diubah menjadi byte dan kemudian byte dapat digunakan untuk mewakili data data dan menyimpan data.
Bentuk pengkodean:

  1. Kode ASCII: digunakan untuk mewakili karakter bahasa Inggris.Ia menggunakan 7 bit untuk mewakili 128 karakter (termasuk huruf besar dan kecil, angka, tanda baca, dan beberapa karakter kontrol), tetapi tidak mendukung karakter Cina. Di sini, satu karakter sama dengan satu byte
  2. Unicode (UTF8): UTF-8 adalah bentuk pengkodean dengan panjang variabel yang mencakup karakter dari semua sistem penulisan di seluruh dunia. Ini kompatibel dengan kumpulan karakter ASCII dan mendukung karakter Cina, termasuk karakter dari semua sistem penulisan di seluruh dunia karakter sesuai dengan 1-4 karakter.
  3. GBK: menggunakan pengkodean panjang variabel, terutama digunakan untuk pengkodean karakter Cina, satu karakter setara dengan 1-2 byte

Metodenya berbeda:

  1. getBytes(): Dapatkan referensi ke array byte. Objeknya adalah karakter.
  2. getBytes().length: Dapatkan panjang array byte, objeknya adalah karakter
  3. getData(): Yang diperoleh adalah referensi ke string yang terdiri dari karakter. Objeknya adalah byte.
  4. getLength(): Panjang string yang diperoleh, objeknya adalah byte
  5. getAddress(): Dapatkan alamat IP, objeknya adalah DatagramPacket
  6. getPort(): Dapatkan nomor port Prot, objeknya adalah DatagramPacket
  7. getSocketAddress(): Dapatkan alamat IP dan nomor port Prot, objeknya adalah DatagramPacket
  8. InetAddress.getByName(): Metode ini dapat mengurai nama host dan mengembalikan alamat IP dari nama host, atau secara langsung mengembalikan objek InetAddress dari alamat IP yang diberikan. Objek InetAddress yang diperoleh diteruskan ke server, dan server dapat menyelesaikannya IP dengan mendapatkan alamat ini.

1.2.5 Mengimplementasikan server terjemahan kamus UDP

Di sini kita dapat menerapkan gagasan pewarisan dan polimorfisme untuk mengimplementasikan server ini, karena perbedaan penting antara server terjemahan kamus dan server gema adalah pemrosesan respons, sehingga kita dapat mewarisi dan menggunakan kembali kode yang diulang dan memperluas kode yang diperlukan.

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

Untuk mengimplementasikan terjemahan kamus ini, Anda juga memerlukan peta dalam struktur data, dan menggunakan pasangan nilai kunci di peta untuk menyimpan data.
Masukkan deskripsi gambar di sini
Kemudian operasi bisnis tertentu hanya perlu menulis ulang metode prosesnya.
Masukkan deskripsi gambar di sini
Saat dijalankan di sini, meskipun ini mengacu pada objek udpEchoServer dari kelas induk, karena subkelas udpDictServer mewarisi kelas induk udpEchoServer dan mengesampingkan metode proses, metode proses yang dijalankan karena fitur polimorfik sebenarnya adalah proses dari metode subkelas.

2. Proses klien dan server

  1. Dapatkan data dari konsol
  2. Klien mengirimkan data ke server
  3. Server menerima data yang dikirim oleh klien
  4. Hitung respons
  5. Server mengirimkan respons yang dihitung ke klien
  6. Klien menerima respons yang dikirim oleh server
  7. Mencetak respons yang dikirim dari server yang diterima dari klien ke konsol