【问题标题】:StreamReader ReadLine Memory LeakStreamReader ReadLine 内存泄漏
【发布时间】:2014-06-29 00:56:16
【问题描述】:

我正在制作一个服务器,我注意到它有一点奇怪的内存泄漏。在我的服务器上,我将一个 IP 地址可以建立的总连接数限制为 8。这非常有效。

但是,当我使用 LOIC 对我的服务器进行 DoS 攻击时,我注意到虽然它只创建了网络类的 8 个实例,但 StreamReader 的 ReadLine 方法占用了很大一部分内存。

我已经使用 Console.WriteLine 验证了实际上没有收到任何数据,它只是在该方法处等待。内存增加并填满了我的整个 16GB。

请注意,这个类的实例只有 8 个来自一个 IP,而且由于我是 DoS 攻击而不是 DDoS 攻击,它只来自我的 IP(我已经验证了这一点)。

这个问题的原因是什么,我该如何解决?

编辑:
相关代码为:

        string data;
        Dictionary<string, string> variables = null;
        try {

            while (_listen) {

                data = null;

                while ((data = _reader.ReadLine()) != null) {

【问题讨论】:

  • 如果您不发送换行符 (\r\n),那么该行将不断增加
  • @LucasTrzesniewski 我不选择发送的内容。这是我对我的服务器运行的 DoS 攻击。
  • 我知道,这只是解释为什么这个东西会消耗内存。我的意思是如果你关心 DoS 攻击,你不应该使用ReadLine
  • 嗯,好的,谢谢。你会推荐什么?
  • 我会写一个答案。

标签: c# memory tcpclient tcplistener


【解决方案1】:

ReadLine 函数会将数据缓冲到一个字符串中,它遇到\r\n(单独\n 不会这样做)。它为此使用StringBuilder。因此,如果您收到的数据不包含序列\r\n,它最终会为单个字符串分配大量内存。

您有一个简单的解决方案:您必须限制服务器愿意读取的最大字符串长度。这是处理恶意数据所必需的 - 如果您的服务器可能是 DoS 攻击的受害者,请不要相信您收到的数据。

所以,解决方案,作为TextReader 扩展方法:

public static String ReadLineSafe(this TextReader reader, int maxLength)
{ 
    var sb = new StringBuilder();
    while (true) {
        int ch = reader.Read();
        if (ch == -1) break; 
        if (ch == '\r' || ch == '\n')
        { 
            if (ch == '\r' && reader.Peek() == '\n') reader.Read(); 
            return sb.ToString();
        } 
        sb.Append((char)ch);

        // Safety net here
        if (sb.Length > maxLength)
            throw new InvalidOperationException("Line is too long");
    }
    if (sb.Length > 0) return sb.ToString();
    return null; 
}

这是原始的ReadLine 代码,添加了安全检查。

哦,您应该将NetworkStream 包装在BufferedStream 中以供网络读取,以避免在每个字节上调用recv

【讨论】:

  • 只是一个简单的问题。如果接收到的数据长度不可预测怎么办。假设我在描述中有一个用户类型,如果我将 512 指定为 maxLength,它会读取所有 2048 字节的数据吗?
  • 根据您的用例,您必须考虑您期望接收的数据的合理上限是多少。例如,用户不太可能在字段中输入 1 MB 的文本。然后,添加一些安全余量并使用它。但是您应该设置的限制是特定于应用程序的。上面的函数不会读取超过maxLength 字符。
  • 好的好的,谢谢。我将使用此代码。如果它工作正常,我会将其标记为答案。
  • 我尝试了这种方法,而不是仅仅降低我的电脑速度并填充内存,它实际上是崩溃了。会不会是这个方法造成的?
  • 忽略我之前的评论,这是我的代码中的一个错误,而不是你的。效果很好,这修复了内存泄漏。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-08
  • 2013-01-20
  • 2011-10-31
相关资源
最近更新 更多