Переполнение буфера в .NET без ошибок - PullRequest
2 голосов
/ 05 апреля 2010

У меня есть один поток, который получает данные через сокет, как это:

while (sock.Connected)
{
    // Receive Data (Block if no data)
    recvn = sock.Receive(recvb, 0, rlen, SocketFlags.None, out serr);

    if (recvn <= 0 || sock == null || !sock.Connected)
    {
        OnError("Error In Receive, recvn <= 0 || sock == null || !sock.Connected");
        return;
    }
    else if (serr != SocketError.Success)
    {
         OnError("Error In Receive, serr = " + serr);
         return;
    }

    // Copy Data Into Tokenizer
    tknz.Read(recvb, recvn);

    // Parse Data
    while (tknz.MoveToNext())
    {
        try
        {
            ParseMessageAndRaiseEvents(tknz.Buffer(), tknz.Length);
        }
        catch (System.Exception ex)
        {
            string BadMessage = ByteArrayToStringClean(tknz.Buffer(), tknz.Length);
            string msg = string.Format("Exception in MDWrapper Parsing Message, 
                           Ex = {0}, Msg = {1}", ex.Message, BadMessage);
            OnError(msg);
        }
    }
}

И я продолжал видеть случайные ошибки в моей функции синтаксического анализа, указывающие, что сообщение было недействительным.Сначала я подумал, что мой класс токенизатора сломан.Но после регистрации всех входящих байтов на токенизаторе получается, что необработанные байты в recvb не были действительным сообщением.Я не думал, что такие поврежденные данные возможны с потоком данных tcp.

Я подумал, что это должен быть какой-то тип переполнения буфера, поэтому я установил

sock.ReceiveBufferSize = 1024 * 1024 * 8;

и анализошибка никогда не возникает при тестировании (это случается достаточно часто для репликации, если я не изменяю ReceiveBufferSize).

Но мой вопрос: почему я не увидел исключение или состояние ошибки или что-то, если внутренний буфер сокета переполнялся до того, как я изменил этот размер буфера?

Ответы [ 2 ]

4 голосов
/ 05 апреля 2010

Я предполагаю, что ваш токенизатор ожидает текст (Utf8?), Но потоки (socket-) работают с байтовыми данными Возможно, что многобайтовый символ разделен в транспорте. Небольшой буфер увеличивает вероятность этого.

Если вы используете ASCII, вы в безопасности, иначе решение будет заключаться в использовании TextReader как промежуточного звена.

2 голосов
/ 05 апреля 2010

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

Это распространенная ошибка при использовании Socket.Send , которая может объяснить, почему вы видите, что проблема исчезает при увеличении размера буфера.

Отправитель обязан повторить попытку, пока все байты не будут успешно записаны.

...