Несколько TCP-клиентов в C#
Один слушатель принимает несколько клиентов
подряд: после каждого AcceptTcpClientAsync
соединение обрабатывают и снова ждут следующее,
пока не вызовут Stop.
В одном процессе сервер запускают в фоновой задаче,
а два клиента подключаются по очереди к
127.0.0.1:18080. Готовность отмечают через
TaskCompletionSource сразу после Start,
и только потом клиенты подключаются.
Сервер печатает префикс "client:" и прочитанную
строку для каждого подключения:
using System.Net;
using System.Net.Sockets;
using System.Text;
TaskCompletionSource ready = new();
Task server = Task.Run(async () =>
{
TcpListener listener = new(IPAddress.Loopback, 18080);
listener.Start();
ready.SetResult();
for (int i = 0; i < 2; i++)
{
using TcpClient peer = await listener.AcceptTcpClientAsync();
using NetworkStream stream = peer.GetStream();
byte[] buf = new byte[256];
int n = await stream.ReadAsync(buf);
string line = Encoding.UTF8.GetString(buf, 0, n).TrimEnd();
Console.WriteLine("client: " + line);
}
listener.Stop();
});
await ready.Task;
async Task Send(string text)
{
using TcpClient client = new();
await client.ConnectAsync("127.0.0.1", 18080);
using NetworkStream stream = client.GetStream();
await stream.WriteAsync(Encoding.UTF8.GetBytes(text + "\n"));
}
await Send("first");
await Send("second");
await server;
Каждое принятое соединение закрывают через
using, иначе сокеты останутся занятыми.
Пока обмен не закончен, следующий клиент ждет
в очереди приёма. Ниже сервер принимает одного
клиента, увеличивает счетчик и отвечает
"ok". В консоли будут число 1 и
строка "ok":
using System.Net;
using System.Net.Sockets;
using System.Text;
TaskCompletionSource ready = new();
int accepted = 0;
Task server = Task.Run(async () =>
{
TcpListener listener = new(IPAddress.Loopback, 18080);
listener.Start();
ready.SetResult();
using TcpClient peer = await listener.AcceptTcpClientAsync();
using NetworkStream stream = peer.GetStream();
byte[] buf = new byte[256];
await stream.ReadAsync(buf);
accepted++;
Console.WriteLine(accepted); // выведет 1
await stream.WriteAsync(Encoding.UTF8.GetBytes("ok\n"));
listener.Stop();
});
await ready.Task;
using TcpClient client = new();
await client.ConnectAsync("127.0.0.1", 18080);
using NetworkStream stream = client.GetStream();
await stream.WriteAsync(Encoding.UTF8.GetBytes("ping\n"));
byte[] buf = new byte[256];
int got = await stream.ReadAsync(buf);
Console.WriteLine(Encoding.UTF8.GetString(buf, 0, got).TrimEnd()); // выведет "ok"
await server;
Примите двух клиентов подряд на порту
18080 и выведите число принятых
соединений после закрытия слушателя.