在收到TCP连接的大量数据时,请出现记忆例外



我有一个应用程序,该应用程序从TCP连接的现场接收GPRS客户端的数据。GPRS客户端设备不时将失去连接并缓冲数据,恢复连接后,所有缓冲数据都发送到TCP连接,从而引起我的应用程序以投掷系统。

我认为这是因为接收到的数据大于我的缓冲区大小(设置为int.maxvalue)。

  1. 如何防止我的应用程序用完存储器?
  2. 我如何确保我不会丢失任何不在的数据?

以下是用于收听的代码,并处理Incomming Data

public void Listen(string ip, int port)
{
    _logger.Debug("All.Tms.SensorDataServer : SensorDataListener : Listen");
    try
    {
        var listener = new TcpListener(IPAddress.Parse(ip), port);
        listener.Start();
        while (true)
        {
            var client = listener.AcceptTcpClient();
            client.SendBufferSize = int.MaxValue;
            var thread = new Thread(() => ReadAndHandleIncommingData(client));
            thread.IsBackground = true;
            thread.Start();
        }
    }
    catch (Exception ex)
    {
        _logger.Error("TMS.Sensor.SensorDataServer : SensorDataListener : Error : ", ex);
    }  
}

private void ReadAndHandleIncommingData(TcpClient connection)
{
     try
     {
         var stream = connection.GetStream();
         var data = new byte[connection.ReceiveBufferSize];
         var bytesRead = stream.Read(data, 0, System.Convert.ToInt32(connection.ReceiveBufferSize));
         var sensorDataMapper = new SensorDataMapperProvider().Get(data);
         if (sensorDataMapper != null)
         {
             _sensorDataHandler.Handle(sensorDataMapper.Map(data));
         }
    }
    catch (Exception ex)
    {
        _logger.Error("TMS.Sensor.SensorDataServer : SensorDataListener : ReadAndHandleIncommingData : Error : ", ex);
    }
    finally
    {
        try
        {
            connection.Close();
        }
        catch(Exception ex)
        {
            _logger.Error("All.Tms.SensorDataServer : SensorDataListener : ReadAndHandleIncommingData : Error : ", ex);
        }
    }
}

关于缓冲器

OutOfMemoryException s当没有顺序存储器左时抛出。
就您而言,这意味着connection.ReceiveBufferSize太大,无法在一件方面保持记忆力。不是因为收到的数据大于您的缓冲区大小

您可以使用较小的,固定的缓冲区获取接收的字节,将其附加在某个地方,然后使用相同的缓冲区接收其余数据,直到拥有所有数据为止。

要注意的一件事是您用于存储收到数据的集合。例如,您不能使用 List<byte>,因为它将其元素存储在引擎盖下的一个阵列中,这比一口气一起来没有区别 - 就像您现在一样。

您可以看到Memory Tributary,这是用于替换MemoryStream的流实现。您可以将其流将其复制到该流并将其保存为流。此页面还包含许多信息,可以帮助您了解OutOfMemoryExceptions。

的原因

此外,我写了一位缓冲区经理,以提供固定尺寸的缓冲区。您可以在这里的代码评论中找到。

关于线程

创建每个连接的线程野蛮。它们的价格为1 MB,因此您应该使用ThreadPool或更好的IOCP(通过Socket类的异步方法)。

您可能想研究这些有关插座编程的常见陷阱和最佳实践:

  • Stephen Cleary(博客)|TCP/IP .NET插座FAQ
  • 堆栈溢出|如何编写基于TCP/IP的可扩展服务器
  • 代码项目|C#socketAsynceventargs高性能套接字代码

使用固定的接收缓冲区,然后逐步解析

相关内容

  • 没有找到相关文章

最新更新