Ketika kita berbicara tentang jaringan, kita tidak bisa tidak menyebutkan model OSI.

Dalam hal model ini, saat ini kami paling tertarik pada lapisan transport (4).

Ini adalah level di mana kami bekerja dengan data yang bergerak "dari titik A ke titik B". Tugas utama lapisan transport adalah memastikan bahwa pesan terkirim ke tujuan, sambil mempertahankan urutan yang benar. Dua protokol lapisan transport yang paling umum adalah: TCP dan UDP. Mereka bekerja secara konseptual dengan cara yang berbeda, tetapi masing-masing memiliki kelebihannya sendiri yang memungkinkan mereka untuk memecahkan masalah tertentu.

Pertama, mari kita lihat cara kerja TCP.

TCP (Transmission Control Protocol) adalah protokol jaringan yang memastikan bahwa koneksi antara host dibuat sebelum data dipertukarkan.

Ini adalah protokol yang sangat andal, karena setiap kali mengirimkan paket data lain, ia harus memeriksa apakah paket sebelumnya telah diterima.

Paket yang dikirim dipesan, dan jika ada masalah dengan paket tertentu (yaitu pihak penerima tidak mengkonfirmasi bahwa paket telah tiba), maka paket dikirim lagi. Akibatnya, kecepatan transfer relatif rendah, karena diperlukan lebih banyak waktu untuk pemantauan yang ketat dan untuk memastikan pemesanan yang benar.

Di sinilah "saudaranya", protokol UDP, masuk. Tidak seperti TCP, UDP tidak terlalu peduli dengan urutan dan status setiap paket. Itu hanya mengirim data tanpa konfirmasi pengiriman. Terlebih lagi, itu tidak membuat koneksi dan tidak bergantung pada status koneksi dengan cara apa pun.

Tujuannya hanya untuk mengirim data ke alamat. Dan ini menimbulkan kerugian utama protokol, keandalan yang rendah, karena dapat dengan mudah kehilangan potongan data. Selain itu, penerima harus siap menghadapi kenyataan bahwa data mungkin tiba rusak. Yang mengatakan, protokol juga memiliki keunggulan, kecepatan transfer yang lebih tinggi, karena protokol terbatas pada pengiriman data.

Ada juga perbedaan dalam bagaimana data itu sendiri ditransmisikan. Di TCP, data dialirkan, artinya data tidak memiliki batas. Dalam UDP, data ditransmisikan sebagai datagram dan memiliki batasan, dan penerima memeriksa integritas data, tetapi hanya jika pesan berhasil diterima.

Mari kita rangkum:

TCP adalah protokol yang andal dan akurat yang mencegah kehilangan data. Sebuah pesan akan selalu terkirim dengan akurasi maksimal, atau tidak terkirim sama sekali. Penerima tidak memerlukan logika untuk memesan data, karena data yang masuk sudah dipesan. UDP tidak dapat diandalkan, tetapi merupakan protokol transfer data yang lebih cepat. Pihak pengirim dan penerima membutuhkan beberapa logika tambahan untuk bekerja dengan protokol ini. Tapi mari kita lihat cara kerjanya menggunakan contoh game komputer atau game seluler yang dimainkan melalui jaringan. Kami mungkin tidak lagi peduli tentang apa yang seharusnya tiba 5 detik yang lalu, dan kami dapat melewati beberapa paket jika paket tidak tiba tepat waktu — permainan mungkin lambat, tetapi Anda masih bisa bermain!

Di Java, untuk bekerja dengan datagram yang dikirimkan melalui UDP, kami menggunakan objek dari kelas DatagramSocket dan DatagramPacket .

Untuk bertukar data, pengirim dan penerima membuat soket datagram, yaitu turunan dari kelas DatagramSocket . Kelas memiliki beberapa konstruktor. Perbedaan di antara mereka adalah di mana soket yang dibuat akan terhubung:

Soket Datagram () Menghubungkan ke port yang tersedia di mesin lokal
DatagramSocket (port int) Terhubung ke port yang ditentukan pada mesin lokal
DatagramSocket (port int, alamat InetAddress) Terhubung ke port yang ditentukan di alamat di mesin lokal (addr)

Kelas berisi banyak metode untuk mengakses dan mengelola parameter soket (kita akan melihatnya nanti), serta metode untuk menerima dan mengirim datagram:

kirim (paket Paket Datagram) Mengirimkan datagram yang dikemas dalam paket
terima (paket DatagramPacket) Menerima datagram yang dikemas dalam paket

DatagramPacket adalah kelas yang mewakili paket datagram. Paket datagram digunakan untuk mengimplementasikan layanan pengiriman paket tanpa koneksi. Setiap pesan dialihkan dari satu mesin ke mesin lain hanya berdasarkan informasi yang terkandung dalam paket itu. Beberapa paket yang dikirim dari satu mesin ke mesin lainnya dapat dirutekan secara berbeda dan dapat tiba dalam urutan apa pun. Pengiriman paket tidak dijamin.

Konstruktor:

DatagramPacket(byte[] buf, panjang int) Membuat DatagramPacket untuk menerima paket dengan panjang length .
DatagramPacket(byte[] buf, panjang int, alamat InetAddress, port int) Membuat paket datagram untuk mengirim paket dengan panjang panjang ke nomor port yang ditentukan pada host yang ditentukan.
DatagramPacket(byte[] buf, int offset, panjang int) Membuat DatagramPacket untuk menerima paket dengan length length , menentukan offset dalam buffer.
DatagramPacket(byte[] buf, int offset, panjang int, alamat InetAddress, port int) Membuat paket datagram untuk mengirim paket dengan panjang panjang dengan offset offset ke nomor port yang ditentukan pada host yang ditentukan.
DatagramPacket(byte[] buf, int offset, int length, alamat SocketAddress) Membuat paket datagram untuk mengirim paket dengan panjang panjang dengan offset offset ke nomor port yang ditentukan pada host yang ditentukan.
DatagramPacket(byte[] buf, int length, alamat SocketAddress) Membuat paket datagram untuk mengirim paket dengan panjang panjang ke nomor port yang ditentukan pada host yang ditentukan.

Kami ingat bahwa pendekatan UDP tidak membuat koneksi. Paket dikirim dengan harapan penerima mengharapkannya. Tetapi Anda dapat membuat koneksi menggunakan metode connect(InetAddress addr, int port) dari kelas DatagramSocket .

Koneksi satu arah dibuat dengan host berdasarkan alamat dan port: baik untuk mengirim atau menerima datagram. Koneksi dapat diakhiri menggunakan metode disconnect() .

Mari kita coba menulis kode server berdasarkan DatagramSocket untuk menerima data:


import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

class Recipient {

   public static void main(String[] args) {
       try {
           DatagramSocket ds = new DatagramSocket(1050);

           while (true) {
               DatagramPacket pack = new DatagramPacket(new byte[5], 5);
               ds.receive(pack);
               System.out.println(new String(pack.getData()));
           }
       } catch (IOException e) {
           e.printStackTrace();
       }
   }
}

Kami membuat objek DatagramSocket untuk didengarkan di port 1050. Saat menerima pesan, ia mencetaknya ke konsol. Kami akan mengirimkan kata "Halo", jadi kami membatasi ukuran buffer hingga lima byte.

Sekarang kita akan membuat kelas pengirim:


import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

class Sender {
   private String host;
   private int port;

   Sender(String host, int port) {
       this.host = host;
       this.port = port;
   }

   private void sendMessage(String mes) {
       try {
           byte[] data = mes.getBytes();
           InetAddress address = InetAddress.getByName(host);
           DatagramPacket pack = new DatagramPacket(data, data.length, address, port);
           DatagramSocket ds = new DatagramSocket();
           ds.send(pack);
           ds.close();
       } catch (IOException e) {
           System.err.println(e);
       }
   }

   public static void main(String[] args) {
   Sender sender = new Sender("localhost", 1050);
   String message = "Hello";

   Timer timer = new Timer();
   timer.scheduleAtFixedRate(new TimerTask() {
       @Override
       public void run() {
           sender.sendMessage(message);
       }
   }, 1000, 1000);
}

}

Dalam metode sendMessage , kami membuat DatagramPacket dan DatagramSocket , dan mengirim pesan kami. Perhatikan bahwa metode close() digunakan untuk menutup DatagramSocket setelah pesan dikirim.

Setiap detik konsol penerima menampilkan pesan masuk "Halo" yang dikirim oleh pengirim. Ini berarti bahwa komunikasi kita semua bekerja dengan benar.