Обмен UDP-сообщениями в C#
Полный цикл UDP в одной программе связывает основной поток и фоновую задачу приёмника.
Приёмник сначала занимает порт 18081,
читает запрос и шлет ответ. Основной поток
ждет сигнал готовности, передает датаграмму
на 127.0.0.1 и читает ответ на своем
сокете. В конце фоновую задачу дожидаются
через await, клиенты закрываются
через using.
Синхронизацию порта удобно делать через
TaskCompletionSource: приемник
поднимает флаг после привязки, затем
отправитель работает и читает ответ строкой:
using System.Net;
using System.Net.Sockets;
using System.Text;
TaskCompletionSource ready = new();
Task server = Task.Run(async () =>
{
using UdpClient listener = new(18081);
ready.SetResult();
UdpReceiveResult req = await listener.ReceiveAsync();
string reply = "echo:" + Encoding.UTF8.GetString(req.Buffer);
await listener.SendAsync(Encoding.UTF8.GetBytes(reply), req.RemoteEndPoint);
});
await ready.Task;
using UdpClient client = new();
await client.SendAsync(Encoding.UTF8.GetBytes("go"), "127.0.0.1", 18081);
UdpReceiveResult ans = await client.ReceiveAsync();
Console.WriteLine(Encoding.UTF8.GetString(ans.Buffer)); // выведет "echo:go"
await server;
Тот же каркас подходит для других коротких фраз. Главное - не закрывать сокет отправителя до приема ответа и держать приемник в потоке, пока идет обмен:
using System.Net;
using System.Net.Sockets;
using System.Text;
TaskCompletionSource ready = new();
Task server = Task.Run(async () =>
{
using UdpClient listener = new(18081);
ready.SetResult();
UdpReceiveResult req = await listener.ReceiveAsync();
string text = Encoding.UTF8.GetString(req.Buffer);
await listener.SendAsync(Encoding.UTF8.GetBytes("reply:" + text), req.RemoteEndPoint);
});
await ready.Task;
using UdpClient client = new();
await client.SendAsync(Encoding.UTF8.GetBytes("lab"), "127.0.0.1", 18081);
UdpReceiveResult ans = await client.ReceiveAsync();
Console.WriteLine(Encoding.UTF8.GetString(ans.Buffer)); // выведет "reply:lab"
await server;
Отправьте "time" и выведите ответ
"now" в консоли отправителя.
Обменяйтесь фразами "query" и
"answer" в одном запуске. В консоли
должна появиться только строка ответа.