Обмен UDP-сообщениями в Java
Полный цикл в одной программе: фоновый поток слушает
порт, читает запрос и шлёт ответ. Главный поток
узнаёт номер порта, отправляет датаграмму и ждёт
ответ на том же DatagramSocket.
Синхронизацию порта удобно делать через
CountDownLatch: приёмник сигнализирует
после getLocalPort, затем отправитель
работает. Ответ отправитель печатает строкой из
байтов:
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CountDownLatch;
public class Main {
public static void main(String[] args) throws Exception {
CountDownLatch ready = new CountDownLatch(1);
int[] port = new int[1];
Thread receiver = new Thread(() -> {
try (DatagramSocket socket = new DatagramSocket(0)) {
port[0] = socket.getLocalPort();
ready.countDown();
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(
buf,
buf.length,
);
socket.receive(packet);
byte[] reply = "pong".getBytes(
StandardCharsets.UTF_8,
);
DatagramPacket out = new DatagramPacket(
reply,
reply.length,
packet.getAddress(),
packet.getPort(),
);
socket.send(out);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
});
receiver.start();
ready.await();
try (DatagramSocket socket = new DatagramSocket()) {
byte[] data = "ping".getBytes(
StandardCharsets.UTF_8,
);
DatagramPacket packet = new DatagramPacket(
data,
data.length,
InetAddress.getByName("127.0.0.1"),
port[0],
);
socket.send(packet);
byte[] answerBuf = new byte[256];
DatagramPacket answer = new DatagramPacket(
answerBuf,
answerBuf.length,
);
socket.receive(answer);
System.out.println(
new String(
answer.getData(),
0,
answer.getLength(),
StandardCharsets.UTF_8,
),
);
}
}
}
Тот же каркас подходит для других коротких фраз.
Главное не закрывать сокет отправителя до
receive ответа и держать приёмник в
потоке, пока идёт обмен:
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CountDownLatch;
public class Main {
public static void main(String[] args) throws Exception {
CountDownLatch ready = new CountDownLatch(1);
int[] port = new int[1];
Thread receiver = new Thread(() -> {
try (DatagramSocket socket = new DatagramSocket(0)) {
port[0] = socket.getLocalPort();
ready.countDown();
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(
buf,
buf.length,
);
socket.receive(packet);
byte[] reply = "done".getBytes(
StandardCharsets.UTF_8,
);
DatagramPacket out = new DatagramPacket(
reply,
reply.length,
packet.getAddress(),
packet.getPort(),
);
socket.send(out);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
});
receiver.start();
ready.await();
try (DatagramSocket socket = new DatagramSocket()) {
byte[] data = "start job".getBytes(
StandardCharsets.UTF_8,
);
DatagramPacket packet = new DatagramPacket(
data,
data.length,
InetAddress.getByName("127.0.0.1"),
port[0],
);
socket.send(packet);
byte[] answerBuf = new byte[256];
DatagramPacket answer = new DatagramPacket(
answerBuf,
answerBuf.length,
);
socket.receive(answer);
System.out.println(
new String(
answer.getData(),
0,
answer.getLength(),
StandardCharsets.UTF_8,
),
);
}
}
}
Отправьте "time" и выведите ответ
"now" в консоли отправителя.
Обменяйтесь фразами "ask" и
"reply" в одном запуске. На экране
должна появиться только строка ответа.