Руководство Java DatagramChannel
1. DatagramChannel
DatagramChannel - это класс, который представляет открытое соединение с сетевым сокетом (network socket) и использует протокол UDP/IP для чтения или записи данных в сеть (network).
public abstract class DatagramChannel
extends AbstractSelectableChannel
implements ByteChannel, ScatteringByteChannel, GatheringByteChannel, MulticastChannel
UDP
User Datagram Protocol (UDP) (Протокол пользовательских дейтаграмм): Короче говоря, UDP - это протокол с правилами разделения данных на небольшие пакеты, называемые Datagram у отправителя, и правилами их объединения у получателя. UDP подходит для передачи данных по сети в приложениях, требующих низкой задержки.
1 Datagram = 1 Gram of data(1 грамм данных). Datagram не имеет количественного значения. Его размер не является фиксированным и предназначен только для очень небольшого пакета данных.
UDP/IP
Правил, установленных UDP, недостаточно для передачи данных между 2 устройствами, поэтому их необходимо объединить с Internet (Internet Protocol - IP). И у нас есть протокол UDP/IP:
- Internet Protocol (IP):Помогает определять местоположение устройств в сети и передавать пакеты данных через Internet. В частности, в этом случае он будет передавать пакеты Datagram.

Пакеты данных, отправляемые по протоколу UDP/IP, не содержат информации о последовательности и не проверяются, поступают ли они по назначению. При таком простом способе отправки UDP/IP быстрее, но менее надежен, чем другие протоколы, такие как TCP/IP. Эта скорость делает компромисс. Если пакет данных будет потерян при передаче, он не будет отправлен повторно. Поэтому приложения, использующие UDP, должны быть способны переносить ошибки, потери и дублирование.
Технически потеря данных не является уязвимостью в UDP. Причиной этого обычно является качество сетевой инфраструктуры, сетевых маршрутизаторов,...
Примеры нескольких типов сервисов, которые обычно используют UDP:
UDP - это идеальный протокол для сетевых приложений, требующих низкой задержки, таких как игры, голосовая и видеосвязь. Эти примеры могут привести к некоторой потере данных без отрицательного влияния на воспринимаемое качество. Однако в некоторых случаях в дополнение к UDP используются методы прямого исправления ошибок для улучшения качества звука и видео, несмотря на некоторые потери.
Смотрите более подробные статьи об UDP/IP и TCP/IP:
- User Datagram Protocol - UDP
- Transmission Control Protocol - TCP
Иерархия классов и интерфейсов связана с классом DatagramChannel:

- NetworkChannel
- ReadableByteChannel
- WritableByteChannel
- InterruptibleChannel
- MulticastChannel
- ScatteringByteChannel
- ByteChannel
- GatheringByteChannel
- SelectableChannel
- SocketChannel
- ServerSocketChannel
2. Например
В этом примере мы отправим сообщение между 2 программами, запущенными на 2 разных компьютерах. Вот иллюстрация примера:

ReceiverProgram: Программе-получателю необходимо открытьDatagramChannel и прослушать его IP-адрес с определенным портом (port), например "localhost:9999".
ReceiverProgram.java
package org.o7planning.datagramchannel.ex;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
public class ReceiverProgram {
public static DatagramChannel startReceiver() throws IOException {
DatagramChannel receiver = DatagramChannel.open();
// Listening SocketAddress
InetSocketAddress address = new InetSocketAddress("localhost", 9999);
receiver.bind(address); // The receiver is listening at localhost:9999
System.out.println("Receiver started at #" + address);
return receiver;
}
public static String receiveMessage(DatagramChannel receiver) throws IOException {
ByteBuffer buffer = ByteBuffer.allocate(1024);
SocketAddress senderAddress = receiver.receive(buffer);
String message = extractMessage(buffer);
System.out.println("Received message from sender: " + senderAddress);
return message;
}
private static String extractMessage(ByteBuffer buffer) {
buffer.flip();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
String msg = new String(bytes);
return msg;
}
public static void main(String[] args) throws IOException {
DatagramChannel receiver = startReceiver();
while (true) {
String message = receiveMessage(receiver);
System.out.println(" - Message: " + message);
if("Bye!".equals(message)) {
break;
}
}
receiver.close();
System.out.println("Receiver closed!");
}
}
SenderProgram:Программе-отправителю (сообщению) необходимо открыть DatagramChannel и отправить сообщение на адрес прослушивания программы-получателя (ReceiverProgram).
SenderProgram.java
package org.o7planning.datagramchannel.ex;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
public class SenderProgram {
public static DatagramChannel startSender() throws IOException {
DatagramChannel sender = DatagramChannel.open();
// SocketAddress
SocketAddress address = null;
sender.bind(address);
sender.configureBlocking(false);
return sender;
}
public static void sendMessage(DatagramChannel sender, String msg, //
SocketAddress receiverAddress) throws IOException {
ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
sender.send(buffer, receiverAddress);
}
public static void main(String[] args) throws IOException, InterruptedException {
DatagramChannel sender = startSender();
String[] messages = new String[] { "Hello", "How are you?", "Bye!" };
// SocketAddress of the Receiver.
InetSocketAddress receiverAddress = new InetSocketAddress("localhost", 9999);
for (String message : messages) {
// Send message to the Receiver!
sendMessage(sender, message, receiverAddress);
Thread.sleep(2 * 1000); // 2 seconds.
}
sender.close();
}
}Чтобы протестировать приложение, вам необходимо сначала запустить класс ReceiverProgram, а затем запустить класс SenderProgram:
Output:
Receiver started at #localhost/127.0.0.1:9999
Received message from sender: /127.0.0.1:58179
- Message: Hello
Received message from sender: /127.0.0.1:58179
- Message: How are you?
Received message from sender: /127.0.0.1:58179
- Message: Bye!
Receiver closed!3. Static Factory methods
Статические заводские методы:
public static DatagramChannel open() throws IOException
public static DatagramChannel open(ProtocolFamily family) throws IOException4. Methods
public abstract class DatagramChannel
extends AbstractSelectableChannel
implements ByteChannel, ScatteringByteChannel, GatheringByteChannel, MulticastChannelМетоды, унаследованные от интерфейсов ReadableByteChannel и WriteableChannel:
public abstract int read(ByteBuffer dst) throws IOException;
public abstract int write(ByteBuffer src) throws IOException;Методы, унаследованные от интерфейсов ScatteringByteChannel и GatheringByteChannel:
public abstract long read(ByteBuffer[] dsts, int offset, int length) throws IOException;
public final long read(ByteBuffer[] dsts) throws IOException
public abstract long write(ByteBuffer[] srcs, int offset, int length) throws IOException;
public final long write(ByteBuffer[] srcs) throws IOExceptionМетоды, унаследованные от интерфейса SelectableChannel:
public final int validOps()- Руководство Java SelectableChannel
Методы, унаследованные от интерфейсов NetworkChannel и MulticastChannel:
public abstract SocketAddress getLocalAddress() throws IOException;
public abstract DatagramChannel bind(SocketAddress local) throws IOException;
public abstract <T> DatagramChannel setOption(SocketOption<T> name, T value) throws IOException;
MembershipKey join(InetAddress group, NetworkInterface interf) throws IOException;
MembershipKey join(InetAddress group, NetworkInterface interf, InetAddress source) throws IOException;- NetworkChannel
- MulticastChannel
Другие методы:
public abstract DatagramSocket socket();
public abstract boolean isConnected();
public abstract DatagramChannel connect(SocketAddress remote) throws IOException;
public abstract DatagramChannel disconnect() throws IOException;
public abstract SocketAddress getRemoteAddress() throws IOException;
public abstract SocketAddress receive(ByteBuffer dst) throws IOException;
public abstract int send(ByteBuffer src, SocketAddress target) throws IOException;Руководства Java New IO
- Руководство Java ReadableByteChannel
- Руководство Java WritableByteChannel
- Руководство Java Pipe.SinkChannel
- Руководство Java Pipe.SourceChannel
- Руководство Java ScatteringByteChannel
- Руководство Java GatheringByteChannel
- Руководство Java Buffer
- Руководство Java DatagramChannel
- Руководство Java Channel
Show More