WebClub - Всероссийский Клуб Веб-разработчиков
WebClub.RU » Архив » Датаграмные сокеты

Датаграмные сокеты


Дата публикации: 17-03-2013

В предыдущей статье мы говорили о TCP/IP сокетах, которые широко используются для надежной передачи данных. Однако, некоторые приложения требуют более быстрого ответа и для них не так важна надежность передачи данных. Для таких приложений UDP (Протокол датаграмм пользователя) сокеты - возможно самый лучший выбор.

UDP сокеты, также называемые сокетами без установления логического соединения, используют архитектуру клиент-сервер (подобно TCP/IP сокетам). Они также известны как датаграмные сокеты. Вся информация посылается пакетами, которые могут приходить в любом порядке или могут вообще не приходить. Это обстоятельство также подразумевает, что количество информации, которое может быть послано, ограничивается размером пакета. Каждый пакет содержит адрес адресата и порта, но не хранит информацию относительно пакетов, которые были или будут посланы.

Далее показаны шаги, которые обычно выполняются UDP сервером:

1. Создается сокет на необходимом порте.
2. Получается пакет.
3. Посылается любой ответ (снова в форме пакета).
4. Повторяются шаги 2 и/или 3, и наконец, сокет закрывается.

Клиент выполняет следующие шаги:

1. Соединяется с сервером на специфическом порте.
2. Посылает пакет.
3. Посылает любой ответ (снова в форме пакета).
4. Повторяет шаги 2 и/или 3, и наконец, закрывает сокет.

Java поддерживает класс java.net.DatagramSocket как для клиента, так и для сервера. Этот класс поддерживает методы для принятия и установления соединения, посылки и приема пакетов. Логика для пакета скрыта в классе java.net.DatagramPacket. Следующий фрагмент кода показывает типовое приложение клиент/сервер, которое использует UDP сокеты:

// UDPServer.java

import java.net.*;
import java.io.*;

/** The UDP server. */
public class UDPServer {

/** The default port for the server. */
public final static int DEFAULT_PORT = 8001;
/** The version command. */
public final String VERSION_CMD = "VERS";
/** The quit command. */
public final String QUIT_CMD = "QUIT";
/** The server version. */
public final byte[] VERSION = { 'V', '2', '.', '0' };
/** The unknown command. */
public final byte[] UNKNOWN_CMD = { 'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ',
'c', 'o', 'm', 'm', 'a', 'n', 'd' };

/** Runs the server. */
public void runServer() throws IOException {

DatagramSocket s = null;

try {

// The stop flag
boolean stopFlag = false;

// The buffer to hold a datagram packet
byte[] buf = new byte[512];

// Create the socket and bind to a particular port
s = new DatagramSocket(DEFAULT_PORT);

System.out.println("UDPServer: Started on "
+ s.getLocalAddress() + ":"
+ s.getLocalPort());

while(!stopFlag) {

// Receive a packet
DatagramPacket recvPacket = new DatagramPacket(buf, buf.length);
s.receive(recvPacket);

// Extract the command from the packet
String cmd = new String(recvPacket.getData()).trim();

System.out.println("UDPServer: Command: " + cmd);

// The response packet
DatagramPacket sendPacket = new DatagramPacket(buf, 0,
recvPacket.getAddress(),
recvPacket.getPort());

// The number of bytes in the response
int n = 0;

// Handle the command
if (cmd.equals(VERSION_CMD)) {
n = VERSION.length;
System.arraycopy(VERSION, 0, buf, 0, n);
}
else if (cmd.equals(QUIT_CMD)) {
// Stop the server
stopFlag = true;
continue;
}
else {
n = UNKNOWN_CMD.length;
System.arraycopy(UNKNOWN_CMD, 0, buf, 0, n);
}

// Update the response
sendPacket.setData(buf);
sendPacket.setLength(n);

// Send the response
s.send(sendPacket);

} // while(server is not stopped)

System.out.println("UDPServer: Stopped");

}
finally {

// Close
if (s != null) {
s.close();
}

}

}

/** Main. */
public static void main(String[] args) {

try {

UDPServer udpSvr = new UDPServer();
udpSvr.runServer();

}
catch(IOException ex) {
ex.printStackTrace();
}

}

}

// UDPClient.java

import java.net.*;
import java.io.*;

/** The UDP client. */
public class UDPClient {

/** Runs the client. */
public void runClient() throws IOException {

DatagramSocket s = null;

try {

// The buffer
byte[] buf = new byte[512];

// Create a socket on any available port
s = new DatagramSocket();

System.out.println("UDPClient: Started");

// The version command
byte[] verCmd = { 'V', 'E', 'R', 'S' };

// The data to transmit
DatagramPacket sendPacket =
new DatagramPacket(verCmd, verCmd.length,
InetAddress.getByName("127.0.0.1"), 8001);
s.send(sendPacket);

// Fetch the server response
DatagramPacket recvPacket = new DatagramPacket(buf, buf.length);
s.receive(recvPacket);

// Extract the server version
String version = new String(recvPacket.getData()).trim();

System.out.println("UDPClient: Server Version: " + version);

// The quit command
byte[] quitCmd = { 'Q', 'U', 'I', 'T' };

// Shutdown the server
sendPacket.setData(quitCmd);
sendPacket.setLength(quitCmd.length);
s.send(sendPacket);

System.out.println("UDPClient: Ended");

}
finally {

// Close
if (s != null) {
s.close();
}

}

}

/** Main. */
public static void main(String[] args) {

try {

UDPClient client = new UDPClient();
client.runClient();

}
catch(IOException ex) {
ex.printStackTrace();
}

}

}
Давайте начнем вместе с сервера. Метод main() создает образец сервера и вызывает метод runServer(). Этот метод связывается с портом 8001 на локальной главной ЭВМ и ждет пакет. После того, как пакет приходит, он извлекает команду и посылает ответ обратно отправителю (клиенту). Если это была команда выхода, то сервер закрывает себя, а также закрывает сокет, на котором осуществлялось прослушивание. Обратите внимание, что при создании датаграмного пакета для посылки, мы также внедряем адрес адресата и порта.
Клиент начинает работу, соединяясь с сервером на локальной главной ЭВМ на порте 8001, а затем посылает команду для выбора версии сервера. Затем используется класс java.net.InetAddress для определения адреса сервера. После этого он отображает полученный ответ. В заключение, осуществляется посылка команды для выключения сервера и закрытия сокета.

Хотя UDP сначала может показаться не очень удачным выбором для связи, однако для некоторых приложений он является правильным вариантом. Например, если вы писали приложение для контроля сети (потеря пакета, и т.д.), то UDP является привилегированным способом, так как вы можете посылать пакеты адресату и осуществлять подсчет переданных пакетов. С другой стороны, вы можете считать число полученных пакетов. Различие состоит в потерянных пакетах. В целом, UDP интересная вещь для принятия решения, необходимого для работы вашего приложения с сетями.
Домен продается

Популярное

Не так давно в сети появился новый сервис, под названием Dead Man Zero. Этот сервис сделал...
Рынок социальных площадок уже давно стал стабильным. Несмотря на то, что время от времени...
Artisteer 4 – единственный в своем роде продукт, позволяющий автоматизировать работу над созданием...
Октябрь 2018 (14)
Февраль 2017 (3)
Январь 2017 (1)
Август 2016 (1)
Май 2016 (2)
Ноябрь 2015 (1)

Карта сайта: 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

Друзья сайта



Случайная цитата

Неизвестный автор:

"Плохой анкор, вебмастеру укор."

Опрос

Ваша техника?

Настольный компютер
Ноутбук
Смартфон
iPad
iPhone
другое