Есть задача организовать обмен данными между двумя приложениями через сокеты. Понятно одно из них будет сервером другое клиентом. Обмен должен быть относительно плотный, сокеты постоянно открыты с одной и другой стороны. Под каждое клиентское подключение планировал создавать отдельный 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 и повторюсь, сокеты не должны закрываться после отправки данных на входящее подключение