【问题标题】:.NET Sockets Buffer Overflow No Error.NET 套接字缓冲区溢出无错误
【发布时间】:2010-04-04 22:55:00
【问题描述】:

我有一个线程通过这样的套接字接收数据:

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,它经常发生足以复制)。

但我的问题是:如果在我更改此缓冲区大小之前套接字的内部缓冲区溢出,为什么我没有看到异常或错误状态或其他什么?

【问题讨论】:

    标签: c# .net networking sockets tcp


    【解决方案1】:

    我假设您的标记器需要文本(Utf8 ?)但(socket-)流使用字节数据。多字节字符可能在传输中被拆分。一个小的缓冲区会增加发生这种情况的可能性。

    如果您使用的是 ASCII,那么您是安全的,否则解决方案将在于使用 TextReader 作为中间。

    【讨论】:

    • 感谢您的回复。我没有想到这一点。但幸运的是,这是使用 ASCII。我正在接收的数据的数据包结构具有 ascii 字符 31(单位分隔符)作为消息之间的分隔符。仅从 recvb 捕获原始数据并写入文件就表明消息无效(当两条消息明显重叠且它们之间没有字符 31 时,数组中至少有一个点)。
    • @Michael,好的,但仍然检查您的标记器逻辑。从您的代码中,标记器负责重新组装消息。即它必须记住任何不完整的消息并在其后追加新数据,然后再尝试查找下一条消息。
    • 分词器会重新组装消息。这里面肯定有bug。但我认为这不会导致我在这里看到的问题。我在 recvn 内容到达标记器之前记录了它。只需将这些字节写入文件,并且其中的消息不正确(即,两条消息在其中重叠,没有被 ascii 令牌 31 分隔)。
    【解决方案2】:

    我还建议确认数据的发送者正在检查成功写入的字节数,而不是假设所有字节都已成功写入。

    这是使用Socket.Send 时的常见错误,并且可以解释为什么当您增加缓冲区大小时问题会消失。

    发送方有责任重试,直到所有字节都成功写入。

    【讨论】:

    • 感谢您的回复。这是一个很好的观点,它可能在发件人方面。这可以解释为什么套接字没有报告任何错误。如果字节被正确传递但发件人有一些问题并且由于缓冲区已满而没有全部发送给我,那么可能就是这样。我想我应该用wireshark捕获服务器发送的数据包来确认。
    • 我认为你的权利,设法让服务器的人今天记录输出并从他的日志文件中:“send(): short send 98, should be 106.”所以看起来他没有发送所有内容,因为我的接收缓冲区已满。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-12
    • 1970-01-01
    • 2017-05-12
    • 1970-01-01
    • 2021-06-05
    • 2021-06-11
    • 1970-01-01
    相关资源
    最近更新 更多