SslStream отдельная тема

Я пытаюсь отобразить на экране любые данные, которые поступают из потока ssl (с веб-сайта). Поскольку я не знаю, когда поступят данные, я использовал другой поток, который продолжает чтение из потока до тех пор, пока не будут прочитаны байты. Это работает отлично, однако, загрузка моего процессора увеличивается до 25% и остается там (это 1 поток при максимальном использовании, мой компьютер имеет 4 потока). Хотя это имеет смысл, поскольку поток застрял в цикле while, я не ожидал, что экземпляр класса Thread будет занимать весь поток моего ЦП (я могу поклясться, что этого не произошло при использовании простого Client/ Серверное приложение).

Поток начинает работать, как только соединение инициализируется, пользователь может отправлять данные на веб-сайт в любое время, когда он хочет, и приложение должно распечатать ответ. Каковы альтернативные решения для этого? Должен ли я отказаться от SslStream и начать использовать что-то еще?

Вот код, который выполняется в этом отдельном потоке:

    void ReadDataAsync(Object obj) {
        byte[] buffer = new byte[65536]; //65536, make sure all bytes can be
                                         //from a single packet
        int bytesRead = -1;

        while (true) {
            //It makes sense for sslStream.Read to block until bytes have been
            //read, but it doesn't.  Which is why I'm checking if bytesRead!=0

            bytesRead = sslStream.Read(buffer, 0, 65536);

            if (bytesRead != 0) {
                Console.WriteLine(Encoding.UTF8.GetString(buffer, 0, bytesRead));
                buffer = new byte[65536];
            }
        }
    }

Спасибо всем, я ценю вашу помощь

Редактировать:
Вместо этого я попытался использовать BeginRead и EndRead, как предложил "gt". Для этого я использую BeginRead всякий раз, когда пользователь отправляет запрос. Когда все данные получены, я печатаю их на экране. Кажется, это работает нормально, но я беспокоюсь о том, будут ли какие-либо проблемы в будущем. Есть ли вероятность, что пакеты испортятся? Например, возможно ли, что EndRead не возвращает 0 в конце первого пакета и продолжает читать второй пакет? Если это возможно, как я буду продолжать решать это? Полученные данные - это просто тело уровня http, поэтому я не могу получить доступ к уровню IP заранее, чтобы узнать длину пакета.

    public void SendData(byte[] message) {
        sslStream.Write(message);
        sslStream.Flush();

        //Start reading for response (if not already reading)
        if (sslStream.CanRead) {
            sslStream.BeginRead(buffer, 0, BufferSize, ReadData, null);
        }
    }

    void ReadData(IAsyncResult ar) {
        int bytesRead = sslStream.EndRead(ar);

        if (bytesRead > 0) {
            //data may be on their way so start reading again
            message.Append(Encoding.UTF8.GetString(buffer, 0, bytesRead));
            sslStream.BeginRead(buffer, 0, BufferSize, ReadData, null);
            Console.WriteLine("Data received but more may be on their way...");
        } else {
            //All data arrived (Checking if length is more than 0 since all the
            //data may had already arrived in the previous check (above)
            if (message.ToString().Length > 0) {
                Console.WriteLine(message.ToString());
                //Clear StringBuilder and reset buffer.
                message.Clear();
                buffer = new byte[BufferSize];
            }
        }
    }

еще раз спасибо

1 ответ

Решение

Проводы while(true) обычно это плохой признак... Если ваш код входит в "жесткий" цикл без конечного условия, он будет продолжать цикл и потреблять все доступные ему ресурсы.

Дважды проверьте, что условие "если" выполняет то, что вы ожидаете. Например, что произойдет, если поток будет прочитан более чем в одной части? (например, две части 32768). Это вполне возможно.

Как только вы довольны поведением, вы можете заставить нить немного поспать, прежде чем пытаться Read, с помощью Thread.Sleep(100),

Или попробуйте поискать асинхронный ввод-вывод, используя BeginRead, Посмотрите этот пример на MSDN.


Отредактируйте, чтобы ответить на часть 2 вопроса:

Я подозреваю, что если что-то пойдет не так, то пойдет не так, поэтому используйте защитный код! Решение следующей проблемы заключается в буферизации всех данных, прочитанных из потока. Затем сделайте попытку другого потока прочитать целые пакеты из буфера. Не забудьте использовать блокировки для предотвращения одновременного чтения / записи в буфер.

Также было бы неплохо написать для этого модульные тесты, чтобы охватить "фрагментированное" поведение (а также нормальное поведение).

В качестве альтернативы вы можете посмотреть протокол более высокого уровня, который позаботится об этом за вас. Один из часто упоминаемых мной примеров - это буфер протокола Google.

Другие вопросы по тегам