Создаем портфолио за 1 месяц
К концу месяца: 4 классных проекта в вашем портфолио! Стоимость: 100$. Подробности...
⊗csSpSoFrm 487 of 509 menu
◀ ▶

Границы сообщения TCP в C#

TCP передаёт поток байтов: один вызов WriteAsync на стороне отправителя не обязан совпасть с одним ReadAsync у получателя. Поэтому приложение само задаёт рамку сообщения - часто символ перевода строки \n в конце каждой логической фразы.

Построчный протокол: отправитель дописывает \n, получатель накапливает байты в буфер и режет строки по разделителю. Ниже сервер читает одну строку "ping" и отвечает "pong\n"; клиент печатает ответ без символа перевода строки:

using System.Net; using System.Net.Sockets; using System.Text; Task server = Task.Run(async () => { TcpListener listener = new(IPAddress.Loopback, 18080); listener.Start(); 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('\n'); if (line == "ping") { await stream.WriteAsync(Encoding.UTF8.GetBytes("pong\n")); } listener.Stop(); }); await Task.Delay(30); 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()); await server;

Два WriteAsync подряд могут прийти одним ReadAsync - тогда строки режут через Split('\n') по фактически прочитанной длине. Так клиент отправляет "one\n" и "two\n" двумя вызовами и закрывает отправку через Shutdown. Если обе фразы пришли одним куском, сервер находит их по разделителю:

using System.Net; using System.Net.Sockets; using System.Text; Task server = Task.Run(async () => { TcpListener listener = new(IPAddress.Loopback, 18080); listener.Start(); using TcpClient peer = await listener.AcceptTcpClientAsync(); using NetworkStream stream = peer.GetStream(); byte[] buf = new byte[256]; int n = await stream.ReadAsync(buf); foreach (string part in Encoding.UTF8.GetString(buf, 0, n).Split( '\n', StringSplitOptions.RemoveEmptyEntries)) { Console.WriteLine(part); } listener.Stop(); }); await Task.Delay(30); using TcpClient client = new(); await client.ConnectAsync("127.0.0.1", 18080); using NetworkStream stream = client.GetStream(); await stream.WriteAsync(Encoding.UTF8.GetBytes("one\n")); await stream.WriteAsync(Encoding.UTF8.GetBytes("two\n")); client.Client.Shutdown(SocketShutdown.Send); await server;

Отправьте строку "ask\n", получите ответ "reply: ask\n" и выведите его в консоли клиента одной строкой.

← →
↑
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить