Руководство 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 IOException
4. 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