Задать вопрос
insighter
@insighter
-First time? - Huh? (C#, React, JS)

Как реализовать асинхронный двунаправленный обмен между сокетами?

Есть задача организовать обмен данными между двумя приложениями через сокеты. Понятно одно из них будет сервером другое клиентом. Обмен должен быть относительно плотный, сокеты постоянно открыты с одной и другой стороны. Под каждое клиентское подключение планировал создавать отдельный Task и в нем вести работу с конкретным клиентом.

Собственно подключения клиентов работают хорошо:
private async Task MainLoopAsync()
        {
            while (true) { // ожидание входящих клиентских подключений
                var tcpClient = await _server.AcceptTcpClientAsync();

                new ClientConnection(tcpClient, WriteLog) // клиентское подключение
                    .Listen();   // цикл для прослушивания входящих данных от клиента

                WriteLog($"*** Client connected ({tcpClient.Client.RemoteEndPoint}) ***");
            }
        }

Из-за асинхронности поток освобождается и не блокируется ожидая клиентов.

Но как, в таком же духе реализовать получение от клиентов. На Метаните (да и в других местах), в примерах предлагается в while цикле проверять свойства tcpClient (или его сокета) и если там что то есть, то вычитывать это.
private async Task ListenLoopAsync()
        {
            while (true) {
                try {
                    if (_tcpClient.Available > 0) {
                        await ProceedStream();
                    }
                    if (!_tcpClient.Connected) {
                        WriteLog("Client disconnected");
                        break;
                    }
                }
                catch {
                    WriteLog("listen error");
                    break;
                }
            }
        }


        private async Task ProceedStream()
        {
            var incomeData = new StringBuilder();
            do {
                var readCount = await _stream.ReadAsync(_buffer);
                incomeData.Append(Encoding.UTF8.GetString(_buffer, 0, readCount));
            }
            while (_stream.DataAvailable);

            WriteLog(incomeData.ToString());
        }

При таком подходе поток постоянно работает и нагружает комп (диспетчер задач показывает примерно 7-8% загрузки).

Ожидал у клиентского сокета, что то типа метода ReadDataIfAvailableAsync, но не нашел его. Буду рад просто ссылкам на продвинутые темы работы с сокетами в .NET

PS и повторюсь, сокеты не должны закрываться после отправки данных на входящее подключение
  • Вопрос задан
  • 93 просмотра
Подписаться 1 Средний 2 комментария
Решения вопроса 1
insighter
@insighter Автор вопроса
-First time? - Huh? (C#, React, JS)
Нашел. У TcpSocket есть ссылка на непосредственный сокет, а у него есть метод RecieveAsync который похож на то что нужно.

var readCount = await _tcpClient.Client.ReceiveAsync(b, SocketFlags.None);
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы