Сокеты — это абстракция самого низкого уровня для программистов, работающих в области сетевого программирования. Существует в основном два способа (протокола) того, как должна происходить коммуникация сокетов.
Один из способов устанавливает набор правил и механизмов, ограничивающих коммуникацию, так, что вероятность возникновения ошибки делается очень низкой, но эти дополнительные элементы управления сами замедляют коммуникацию.
Он называется TCP (Transfer Control Protocol). В противоположность этому, другой способ имеет очень мало правил, и поэтому он ускоряет общение, но не гарантирует точность. Он называется UDP (User Datagram Protocol). Если вам будет дан шанс выбрать один из них, какой вы выберете?
Я не собираюсь подробно обсуждать разницу между TCP и UDP, потому что это выходит за рамки данной статьи. Тем не менее, когда мы хотим, чтобы коммуникация была точной, мы должны воспользоваться TCP, потому что это помогает обеспечить бесперебойную связь.
Если вы знакомы с TCP, то наверняка знаете, что он реализует различные механизмы, такие как управление потоком, контроль ошибок, контроль перегрузки и т.д. Однако, когда нашим главным приоритетом является быстрая коммуникация, а не точная, выбор должен быть сделан в пользу UDP.
В этой статье мы узнаем, что такое UDP-сокеты и как продемонстрировать коммуникацию UDP-сокетов, используя Java.
Скорость — основной приоритет для потоковой передачи в реальном времени. Когда футбольный матч транслируется в режиме реального времени, люди, которые смотрят его по телевидению, должны получать обновленную информацию о событиях сразу же, как только они происходят на игровой площадке.
Неспособность поставлять контент в режиме реального времени может критически сказаться на росте поставщика потоковой передачи и его позиции на рынке.
Кроме того, нет никакой пользы в повторной трансляции точных данных, даже если контент был поврежден на пути к конечному пользователю, просто потому, что они больше не являются “контентом в реальном времени”. По этим причинам при взаимодействии в реальном времени UDP предпочтительнее TCP.
Примечание: если вы хотите получить представление о том, что такое сокеты и как работает коммуникация TCP-сокетов, пожалуйста, ознакомьтесь с этой статьей.
Классы DatagramPacket
и DatagramSocket
в Java поддерживают использование коммуникации UDP-сокетов на уровне приложения. Давайте напишем простой сервер и клиент на Java, которые взаимодействуют друг с другом через UDP-сокеты.
В этом примере серверный сокет получает данные типа String
от клиента и отправляет заглавную строку обратно клиенту.
Поскольку мы уже осведомлены об этапах коммуникации UDP-сокетов, я поместил комментарии в обе Java-программы, чтобы объяснить код, а не использовать длинные абзацы. Этот способ также поможет вам быстрее понять код, пока вы будете его читать.
Построение серверного UDP-сокетаimport java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class UDPServer{
// Серверный UDP-сокет запущен на этом порту
public final static int SERVICE_PORT=50001;
public static void main(String[] args) throws IOException{
try{
// Создайте новый экземпляр DatagramSocket, чтобы получать ответы от клиента
DatagramSocket serverSocket = new DatagramSocket(SERVICE_PORT);
/* Создайте буферы для хранения отправляемых и получаемых данных.
Они временно хранят данные в случае задержек связи */
byte[] receivingDataBuffer = new byte[1024];
byte[] sendingDataBuffer = new byte[1024];
/* Создайте экземпляр UDP-пакета для хранения клиентских данных с использованием буфера для полученных данных */
DatagramPacket inputPacket = new DatagramPacket(receivingDataBuffer, receivingDataBuffer.length);
System.out.println("Waiting for a client to connect...");
// Получите данные от клиента и сохраните их в inputPacket
serverSocket.receive(inputPacket);
// Выведите на экран отправленные клиентом данные
String receivedData = new String(inputPacket.getData());
System.out.println("Sent from the client: "+receivedData);
/*
* Преобразуйте отправленные клиентом данные в верхний регистр,
* Преобразуйте их в байты
* и сохраните в соответствующий буфер. */
sendingDataBuffer = receivedData.toUpperCase().getBytes();
// Получите IP-адрес и порт клиента
InetAddress senderAddress = inputPacket.getAddress();
int senderPort = inputPacket.getPort();
// Создайте новый UDP-пакет с данными, чтобы отправить их клиенту
DatagramPacket outputPacket = new DatagramPacket(
sendingDataBuffer, sendingDataBuffer.length,
senderAddress,senderPort
);
// Отправьте пакет клиенту
serverSocket.send(outputPacket);
// Закройте соединение сокетов
serverSocket.close();
}
catch (SocketException e){
e.printStackTrace();
}
}
}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class UDPClient{
/* Порт сервера, к которому собирается
подключиться клиентский сокет */
public final static int SERVICE_PORT = 50001;
public static void main(String[] args) throws IOException{
try{
/* Создайте экземпляр клиентского сокета.
Нет необходимости в привязке к определенному порту */
DatagramSocket clientSocket = new DatagramSocket();
// Получите IP-адрес сервера
InetAddress IPAddress = InetAddress.getByName("localhost");
// Создайте соответствующие буферы
byte[] sendingDataBuffer = new byte[1024];
byte[] receivingDataBuffer = new byte[1024];
/* Преобразуйте данные в байты
и разместите в буферах */
String sentence = "Hello from UDP client";
sendingDataBuffer = sentence.getBytes();
// Создайте UDP-пакет
DatagramPacket sendingPacket = new DatagramPacket(sendingDataBuffer,sendingDataBuffer.length,IPAddress, SERVICE_PORT);
// Отправьте UDP-пакет серверу
clientSocket.send(sendingPacket);
// Получите ответ от сервера, т.е. предложение из заглавных букв
DatagramPacket receivingPacket = new DatagramPacket(receivingDataBuffer,receivingDataBuffer.length);
clientSocket.receive(receivingPacket);
// Выведите на экране полученные данные
String receivedData = new String(receivingPacket.getData());
System.out.println("Sent from the server: "+receivedData);
// Закройте соединение с сервером через сокет
clientSocket.close();
}
catch(SocketException e) {
e.printStackTrace();
}
}
}
Поскольку мы уже создали и сервер, и клиента, давайте запустим обе программы и посмотрим их в действии. Сначала запустите программу UDPServer.java
, а затем UDPClient.java
.
Вы увидите на консоли/терминале вывод каждой программы, как это показано ниже. Это гарантирует, что между нашими сервером и клиентом произошла успешная коммуникация сокетов.
UDPServer.java
Waiting for a client to connect...
Sent from the client: Hello from UDP client
UDPClient.java
sent from the server: HELLO FROM UDP CLIENTВот наше руководство и подошло к концу. Из этой статьи мы узнали, что такое коммуникация UDP-сокетов и как ее продемонстрировать на Java. Я искренне надеюсь, что информация вам пригодится.
Спасибо за чтение!
Перевод статьи : Pavindu Lakshan, “Fundamentals of UDP Socket Programming in Java”
Комментарии