Вы можете запустить задачу для уникального исходного IP: комбинация портов. Это позволит вам легко поддерживать конечный автомат для каждой уникальной комбинации входящего IP-адреса: PORT. System.IO.Pipelines
позволяет очень легко объединить ie.
Сначала создайте UDPListener
задачу, которая имитирует TCPListener
, для каждого нового IP: PORT ускоряет задачу для обработки этот порт, создайте канал и данные eveytime поступают из этой IPEndpoint, поместите данные в PipeWriter
static async Task StartUdpListener()
{
// Use a Dictionary to match packets from given connections to give Pipes
ConcurrentDictionary<string, Pipe> connections = new ConcurrentDictionary<string, Pipe>();
var udpServer = new UdpClient(new IPEndPoint(IPAddress.Any, 33000));
while (true)
{
// Wait for some data to arrive
var result = await udpServer.ReceiveAsync();
if(connections.ContainsKey(result.RemoteEndPoint.ToString()))
{
// If we have seen this IPEndpoint before send the traffic to the pipe
// the task associated with that Pipe willpick the traffic up
connections.TryGetValue(result.RemoteEndPoint.ToString(), out var p);
await p.Writer.WriteAsync(result.Buffer);
}
else
{
// If we have not seen it, make the pipe, stick the data in the pipe
// and spin up a task to Read/Process the data
var p = new Pipe();
connections.TryAdd(result.RemoteEndPoint.ToString(), p);
await p.Writer.WriteAsync(result.Buffer);
_ = Task.Run(() => UdpServerClient(result.RemoteEndPoint.ToString(), p));
}
}
}
Это упрощенное c представление о том, что делает ядро, когда оно получает TCPPacket, оно вставляет его в буфер сокетов для чтения через поток.
Задача UDP Server Client
будет выглядеть примерно так:
static async Task UdpServerClient(string serverName,Pipe p)
{
while (true)
{
var readResult = await p.Reader.ReadAsync();
var message = Encoding.ASCII.GetString(readResult.Buffer.FirstSpan.ToArray());
Console.WriteLine($"Server: {serverName} Received: {message}");
p.Reader.AdvanceTo(readResult.Buffer.End);
}
}
И для полноты, для некоторых клиентов это обычно на разных машинах, но ради простоты мы будем запускать их как Задачи.
static async Task UdpClientClient(string messageToSend)
{
var client = new UdpClient();
client.Connect("127.0.0.1", 33000);
for(var i=0;i<5;i++)
{
var message = ASCIIEncoding.ASCII.GetBytes(messageToSend + " #"+ i.ToString());
await client.SendAsync(message, message.Length);
await Task.Delay(1000);
}
}
}
Свяжите их все вместе:
static async Task Main(string[] args)
{
_ = Task.Run(() => StartUdpListener());
_ = UdpClientClient("hi Server!");
_ = UdpClientClient("I am here server...");
await UdpClientClient("Me too server!");
}
И вы получите это:
Server: 127.0.0.1:53183 Received: Me too server! #0
Server: 127.0.0.1:53182 Received: I am here server... #0
Server: 127.0.0.1:53181 Received: hi Server! #0
Server: 127.0.0.1:53182 Received: I am here server... #1
Server: 127.0.0.1:53183 Received: Me too server! #1
Server: 127.0.0.1:53181 Received: hi Server! #1
Server: 127.0.0.1:53182 Received: I am here server... #2
Server: 127.0.0.1:53183 Received: Me too server! #2
Server: 127.0.0.1:53181 Received: hi Server! #2
Server: 127.0.0.1:53182 Received: I am here server... #3
Server: 127.0.0.1:53181 Received: hi Server! #3
Server: 127.0.0.1:53183 Received: Me too server! #3
Server: 127.0.0.1:53183 Received: Me too server! #4
Server: 127.0.0.1:53181 Received: hi Server! #4
Server: 127.0.0.1:53182 Received: I am here server... #4
Конечно, вам нужна проверка на наличие ошибок, если клиент все еще там и т. Д. c.