Обмен UDP-сообщениями в Kotlin
Полный цикл в одной программе: фоновый поток слушает
порт, читает запрос и шлёт ответ. Главный поток
узнаёт номер порта, отправляет датаграмму и ждёт
ответ на том же DatagramSocket.
Синхронизацию порта удобно делать через
CountDownLatch: приёмник сигнализирует
после localPort, затем отправитель
работает. Ответ отправитель печатает строкой из
байтов:
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.InetAddress
import java.util.concurrent.CountDownLatch
fun main() {
val ready = CountDownLatch(1)
var port = 0
Thread {
DatagramSocket(0).use { socket ->
port = socket.localPort
ready.countDown()
val buf = ByteArray(256)
val packet = DatagramPacket(buf, buf.size)
socket.receive(packet)
val reply = "pong".toByteArray()
val out = DatagramPacket(
reply,
reply.size,
packet.address,
packet.port,
)
socket.send(out)
}
}.start()
ready.await()
DatagramSocket().use { socket ->
val data = "ping".toByteArray()
val packet = DatagramPacket(
data,
data.size,
InetAddress.getByName("127.0.0.1"),
port,
)
socket.send(packet)
val buf = ByteArray(256)
val answer = DatagramPacket(buf, buf.size)
socket.receive(answer)
println(
String(answer.data, 0, answer.length),
)
}
}
Тот же каркас подходит для других коротких фраз.
Главное - не закрывать сокет отправителя до
receive ответа и держать приёмник в
потоке, пока идёт обмен:
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.InetAddress
import java.util.concurrent.CountDownLatch
fun main() {
val ready = CountDownLatch(1)
var port = 0
Thread {
DatagramSocket(0).use { socket ->
port = socket.localPort
ready.countDown()
val buf = ByteArray(256)
val packet = DatagramPacket(buf, buf.size)
socket.receive(packet)
val reply = "done".toByteArray()
val out = DatagramPacket(
reply,
reply.size,
packet.address,
packet.port,
)
socket.send(out)
}
}.start()
ready.await()
DatagramSocket().use { socket ->
val data = "start job".toByteArray()
val packet = DatagramPacket(
data,
data.size,
InetAddress.getByName("127.0.0.1"),
port,
)
socket.send(packet)
val buf = ByteArray(256)
val answer = DatagramPacket(buf, buf.size)
socket.receive(answer)
println(
String(answer.data, 0, answer.length),
)
}
}
Отправьте "time" и выведите ответ
"now" в консоли отправителя.
Обменяйтесь фразами "ask" и
"reply" в одном запуске. На экране
должна появиться только строка ответа.