У наших попередніх двох статтях ми обговорювали, як побудувати простий TCP-клієнт і сервер за допомогою Java. (Читати тут) та як зробити їх багатопотоковими (Читати тут).
У цій останній статті серії про мережеве програмування на Java ми розглянемо, як створити простий, але функціональний UDP-відправник (sender) та приймач (receiver) за допомогою Java. UDP (User Datagram Protocol) — це безз'єднувальний протокол комунікації, що широко використовується в ситуаціях, де критично важлива швидкість, а надійність можна забезпечити на рівні додатка.
Що таке UDP?
UDP розшифровується як User Datagram Protocol і працює поверх IP (Internet Protocol). На відміну від TCP, UDP не встановлює з'єднання перед відправкою даних. Замість цього він надсилає пакети (датаграми) незалежно. Це дозволяє здійснювати швидшу комунікацію, але при цьому відсутні гарантії надійності, порядку доставки та перевірки помилок.
Прикладом додатків, де зазвичай використовується UDP, є відео стрімінг, онлайн-ігри та запити до DNS, де мінімізація затримок важливіша за гарантії доставки.
Щоб продемонструвати, як працює UDP в Java, ми побудуємо два класи:
- UDPSender: виступає в ролі клієнта, який відправляє повідомлення.
- UDPReceiver: виступає в ролі сервера, який приймає повідомлення та відповідає на них.
3.1 UDPSender
import java.io.IOException;
import java.net.*;
import java.util.Objects;
import java.util.Scanner;
public class UDPSender {
public UDPSender() throws IOException {
// Крок 1: Створення DatagramSocket для відправки та отримання датаграм.
DatagramSocket datagramSocket = new DatagramSocket();
Scanner keyboard = new Scanner(System.in);
while(true){
// Крок 2: Запит на введення повідомлення.
System.out.println("Введіть ваше повідомлення: ");
String message = keyboard.nextLine();
// Крок 3: Закриття сокета, якщо користувач введе "quit".
if (Objects.equals(message, "quit")){
datagramSocket.close();
System.out.println("Сокет закрито.");
break;
}
// Крок 4: Перетворення повідомлення в масив байтів.
byte[] buffer = message.getBytes();
// Крок 5: Створення та відправка DatagramPacket на localhost, порт 2021.
DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length, InetAddress.getByName("localhost"), 2021);
datagramSocket.send(datagramPacket);
System.out.println("Відправлено: " + message);
// Крок 6: Підготовка до отримання відповіді від сервера.
buffer = new byte[1500];
datagramPacket = new DatagramPacket(buffer, buffer.length);
datagramSocket.receive(datagramPacket);
// Крок 7: Перетворення отриманого масиву байтів назад у рядок та відображення.
message = new String(buffer).trim();
System.out.println("Отримано: " + message);
}
}
public static void main(String[] args) {
try {
new UDPSender();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Крок 1: Створюється DatagramSocket
, щоб мати змогу відправляти та отримувати датаграми.
- Крок 2: Використовуємо
Scanner
для отримання вводу користувача. - Крок 3: Якщо користувач введе "quit", сокет закривається і цикл завершується.
- Крок 4: Повідомлення перетворюється в масив байтів.
- Крок 5: Створюється
DatagramPacket
з повідомленням, який надсилається серверу на адресуlocalhost
та порт 2021. - Крок 6: Підготовлено буфер для отримання відповіді від сервера.
- Крок 7: Отриманий масив байтів перетворюється в рядок і виводиться на екран.
3.2 UDPReceiver
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPReceiver {
public UDPReceiver() throws IOException {
// Крок 1: Створення DatagramSocket для прослуховування порту 2021.
DatagramSocket datagramSocket = new DatagramSocket(2021);
System.out.println("Приймач працює...");
while(true) {
// Крок 2: Створення буфера та DatagramPacket для отримання даних.
byte[] buffer = new byte[1500];
DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);
datagramSocket.receive(datagramPacket);
// Крок 3: Отримання та виведення отриманого повідомлення.
String message = new String(buffer).trim();
System.out.println("Отримано повідомлення: " + message);
// Крок 4: Отримання адреси та порту відправника.
InetAddress senderAddress = datagramPacket.getAddress();
int senderPort = datagramPacket.getPort();
// Крок 5: Підготовка та відправка повідомлення про підтвердження.
message = "Ok.";
buffer = message.getBytes();
datagramPacket = new DatagramPacket(buffer, buffer.length, senderAddress, senderPort);
datagramSocket.send(datagramPacket);
System.out.println("Відправлено: " + message);
}
}
public static void main(String[] args) {
try {
new UDPReceiver();
} catch (Exception e) {
e.printStackTrace();
}
}
}
- Крок 1:
DatagramSocket
прослуховує порт2021
для вхідних пакетів. - Крок 2: Створюються буфер та
DatagramPacket
для отримання даних. - Крок 3: Повідомлення витягується з буфера та виводиться.
- Крок 4: Отримуються IP-адреса та номер порту відправника.
- Крок 5: Підготовлено та відправлено повідомлення про підтвердження.
Потік роботи
- Запустіть клас
UDPReceiver
, щоб почати прослуховувати порт2021
. - Запустіть клас
UDPSender
, який запитує у користувача повідомлення. Відправник перетворює повідомлення в байти та надсилає його як пакет. - Приймач витягує та відображає повідомлення.
- Приймач відправляє підтвердження ("Ok.") назад до відправника.
- Відправник отримує і відображає підтвердження.
- Користувач може продовжити відправку повідомлень або ввести "quit" для закриття відправника.
Запуск програми
- Спочатку запустіть клас
UDPReceiver
, щоб він був готовий до отримання повідомлень. - Запустіть клас
UDPSender
і вводьте повідомлення для відправки. - Введіть будь-яке повідомлення в відправнику, щоб продовжити комунікацію.
- Введіть "quit" в відправнику, щоб закрити з'єднання.
UDP надає легковажний, швидкий метод комунікації, але потребує ретельної обробки для забезпечення цілісності даних. У цій статті ми продемонстрували створення базового клієнт-серверного додатка UDP на Java.
Це кінець серії з трьох частин. Слідкуйте за новими матеріалами!
Перекладено з: Java Networking Basics : Networking with UDP Sockets