Повторное использование TcpClient и NetworkStream приводит к неверным данным - PullRequest
0 голосов
/ 30 октября 2019

Я пишу приложение для зеркалирования экрана в WPF. Мой оригинальный код отправляет битовый рисунок по TCP с сервера на клиент. Исходный код работает нормально, но закрывает и воссоздает соединение TCP каждый раз, когда отправляет кадр. Это приводит к открытию и закрытию 30 сокетов в секунду, что, я полагаю, не идеальный способ сделать это.

Итак, я попытался переписать его, чтобы повторно использовать поток при каждой отправке данных, но через некоторое время поток начинает выдавать неправильные данные.

public void SendStream(byte[] byteArray)
{
    /*
    _client = IsServer ? _server.AcceptTcpClient() : new TcpClient(IP.ToString(), Port);
    using (var clientStream = _client.GetStream())
    {
        var comp = Compress(byteArray);
        clientStream.Write(comp, 0, comp.Length);
    }
    */

    var comp = Compress(byteArray);
    _stream.Write(BitConverter.GetBytes(comp.Length), 0, 4);
    _stream.Write(comp, 0, comp.Length);
}

public byte[] ReceiveStream()
{
    /*
    _client = IsServer ? _server.AcceptTcpClient() : new TcpClient(IP.ToString(), Port);
    var stream = _client.GetStream();
    return Decompress(stream);
    */

    var lengthByte = new byte[4];
    _stream.Read(lengthByte, 0, 4);
    var length = BitConverter.ToInt32(lengthByte, 0);
    var data = new byte[length];
    _stream.Read(data, 0, length);
    return Decompress(new MemoryStream(data));
}

Функции сжатия и распаковкипросто обертки вокруг встроенного DeflateStream.

Я проверил, что отправленные comp.Length и полученные length одинаковы при возникновении ошибки.

Есть идеи о том, что происходит? Благодарю. Он всегда выдает исключение после, по крайней мере, нескольких кадров, а не первого (по крайней мере, я пробовал до сих пор)

(кажется, что это происходит быстрее, когда растровые изображения больше по размеру, т.е. когда происходит сжатие). Алгоритм не делает так много, потому что экран более сложный. Хотя не уверен на 100%)

1 Ответ

1 голос
/ 30 октября 2019

Попробуйте сделать следующее:

    int receivedBytesCount = _stream.Read(data, 0, length);

Переменная длины, передаваемая методу Read, является максимальной. Метод Read может фактически прочитать меньше байтов, чем длина. Он вернет количество байтов, которые он фактически прочитал. Это произойдет, когда ваши данные будут фрагментированы в пакеты TCP. Вы должны продолжать вызывать Read, пока не получите достаточно байтов и объедините все, чтобы получить полный кадр. Вам нужно будет отрегулировать смещение, чтобы избежать перезаписи буфера. В коде, который вы разместили, он жестко запрограммирован на 0.

...