Датаграмма UDP в C#
UDP передаёт отдельные датаграммы:
каждый вызов SendAsync несёт один пакет
байтов с границами, заданными отправителем. Соединение
как в TCP не устанавливается.
Один пакет - один вызов приёма ReceiveAsync
на стороне слушателя. Чтобы пример был
самодостаточным, приёмник поднимают в
Task.Run на порту 18081.
Сразу после привязки он отмечает готовность
через TaskCompletionSource, и отправитель
ждёт эту отметку, иначе пакет уйдёт в пустоту.
Затем отправляют текст
"ping" на 127.0.0.1. В консоли
появится "ping":
using System.Net;
using System.Net.Sockets;
using System.Text;
TaskCompletionSource ready = new();
Task listener = Task.Run(async () =>
{
using UdpClient server = new(18081);
ready.SetResult();
UdpReceiveResult packet = await server.ReceiveAsync();
Console.WriteLine(Encoding.UTF8.GetString(packet.Buffer, 0, packet.Buffer.Length));
});
await ready.Task;
using UdpClient sender = new();
byte[] payload = Encoding.UTF8.GetBytes("ping");
await sender.SendAsync(payload, payload.Length, "127.0.0.1", 18081);
await listener;
Два SendAsync подряд дают две независимые
датаграммы - получатель прочитает их двумя
ReceiveAsync в том же порядке, если сеть
не потеряла пакеты. На localhost потери
редки; в интернете порядок и доставка не
гарантируются без дополнительного протокола:
using System.Net;
using System.Net.Sockets;
using System.Text;
TaskCompletionSource ready = new();
Task listener = Task.Run(async () =>
{
using UdpClient server = new(18081);
ready.SetResult();
for (int i = 0; i < 2; i++)
{
UdpReceiveResult packet = await server.ReceiveAsync();
Console.WriteLine(Encoding.UTF8.GetString(packet.Buffer, 0, packet.Buffer.Length));
}
});
await ready.Task;
using UdpClient sender = new();
await sender.SendAsync(Encoding.UTF8.GetBytes("first"), "127.0.0.1", 18081);
await sender.SendAsync(Encoding.UTF8.GetBytes("second"), "127.0.0.1", 18081);
await listener;
Примите одну датаграмму с текстом "lab"
и выведите число байтов в пакете.