socket编程exe文件内存逐渐增加,socket也保持打开状态 [英] socket programming exe file memory increasing gradually and also socket remain open

查看:70
本文介绍了socket编程exe文件内存逐渐增加,socket也保持打开状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当从多个客户端收到sting时,某个套接字保持打开所以创建错误的文件大小逐渐增加所以在时间exe文件从
35 kb变为2 GB所以我怎样才能减少开放的sockect

When received sting from multiple client at time some socket remain open so created mis file size increasing gradually so at time exe file become 2 GB from 35 kb so how can i reduce open sockect

private void Server_Load(object sender, EventArgs e)
{
  try
   {
        this.tcpListener = new TcpListener(IPAddress.Any, port);
        this.listenThread = new Thread(new ThreadStart(ListenForClients));
        this.listenThread.Start();
   }
  catch (Exception ex)
  { }
  finally
  {
    if (this.tcpListener != null)
    {
        this.tcpListener.Stop();
    }
  }
} 

Mangae Client request by server continuously from load method

private void ListenForClients()
{
 TcpClient client = null;
 try
 {
    this.tcpListener.Start();
    while (true)
    {
         client = this.tcpListener.AcceptTcpClient();
        ThreadPool.QueueUserWorkItem(new WaitCallback(HandleClientComm), 
     client);
    }
 }
 catch (Exception ex)
 {
    LogHelperISPL.Logger.Info("ListenForClients: " + ex.Message);
    this.tcpListener.Stop();
 }
 finally
 {
    if(this.tcpListener != null)
    {
        this.tcpListener.Stop();
    }
    if (client != null)
    {
        client.Close();
    }
 }
}

Take data from client and insert into table and mange pass tcpclient and networkstream with close connection

private void HandleClientComm(object client)
{
 TcpClient tcpClient = null;
 NetworkStream clientStream = null;
 try
 {
    tcpClient = (TcpClient)client;
    clientStream = tcpClient.GetStream();
    string InsertedRecord = string.Empty;
    byte[] messageBytes = new byte[4096];
    int bytesRead;
    bool end = false;
    while (!end)
    {
        bytesRead = 0;
        try
        {
            if (clientStream != null)
            {
                bytesRead = clientStream.Read(messageBytes, 0, 
            messageBytes.Length);
            }                        
        }
        catch (SocketException ex)
        {
            if (clientStream != null)
            {
                clientStream.Flush();
                clientStream.Close();
            }
            if (tcpClient != null)
            {
                tcpClient.Close();
            }
            break;
        }
        catch (Exception ex)
        {
            if (clientStream != null)
            {
                clientStream.Flush();
                clientStream.Close();
            }
            if (tcpClient != null)
            {
                tcpClient.Close();
            }
            break;
        }
        if (bytesRead <= 0)
        {
            break;
        }
        ASCIIEncoding encoder = new ASCIIEncoding();
        string Datareceived = encoder.GetString(messageBytes, 0, bytesRead);
        if (!string.IsNullOrEmpty(Datareceived))
        {
            string[] Multistrings = Datareceived.Split('!');
            for (int i = 0; i < Multistrings.Length; i++)
            {
                if (!string.IsNullOrEmpty(Multistrings[i]))
                {
                    if (Multistrings[i].Length >= 90)
                    {
                        InsertedRecord = InsertRawData(Multistrings[i]);
                    }
                    else
                    {
                        InsertedRecord = 
       InsertRawDataGarbage(Multistrings[i]);
                    }
                }
            }
        }
    }
 }
 catch (Exception ex)
 {
    LogHelperISPL.Logger.Info("While loop: " + ex.Message);
 }
 finally
 {
    if (clientStream != null)
    {
        clientStream.Flush();
        clientStream.Close();
    }
    if (tcpClient != null)
    {
        tcpClient.Close();
    }
 }
}

推荐答案

什么文件?我的代码中没有任何地方可以看到任何类型的文件变得更大。您是在谈论程序使用的内存量吗? 

What file? Nowhere in your code do I see a mention of any sort of file to grow larger. Are you talking about the amount of memory your program is using? 

您需要进行大量的异常处理,这使得此代码难以阅读。我注意到在你的while循环中你正在读4K数据。然后将该数据转换为字符串。然后你拆分字符串。最后你调用一些方法
InsertRawData或InsertRawDataGarbage。然后你又回来了。你真的想把数据限制在4K吗?给定循环逻辑,您可以轻松地将有效数据(在4K边界上被破坏)识别为垃圾。你不应该首先阅读
中的所有数据吗?

You have a lot of exception handling that isn't necessary which is making this code harder to read. I do notice in your while loop you are reading 4K of data. Then you convert that data into a string. Then you split the string. Finally you call some method InsertRawData or InsertRawDataGarbage. Then you loop around again. Are you really wanting to limit the data to 4K? Given your loop logic you could easily identify valid data (that is broken on the 4K boundary) as garbage. Shouldn't you read all the data in first?

你也在进行大量的转换。对于那个单字节数组,你要分配一个字符串,然后分配一个字符串数组。更不用说编码器了。每次循环都会发生这种情况。

Also you're doing a lot of conversions. For that single byte array you're allocating a string and then a string array. Not to mention the encoder. This happens each time through your loop.

我首先建议你考虑使用BinaryReader或StringReader(如果你知道它是一个字符串)。然后立即读取整个数据。然后使用一个简单的IndexOf来查找感叹号(或者只是修改你的解析来明确地执行这个
)。这将削减一些分配。还要考虑将编码器移到循环外部,因为它只需要一次。 

I would start with recommending that you consider using either a BinaryReader or StringReader (if you know it is a string). Then read the entire data in at once. Then use a simple IndexOf to find the exclamation (or simply modify your parsing to do this explicitly). That would cut down on a couple of allocations. Also consider moving the encoder outside the loop as it is only needed once. 

我还建议你清理错误处理。您通常不需要嵌套处理,您真正需要做的就是检查null并关闭流/客户端。这应该是你需要的唯一try-catch块。取决于你想要恢复的
进程中的位置决定了它的去向,但我想的只是HandleClientComm方法中的一个try-catch。使用using语句可以大大清理此代码。

I would also suggest you clean up your error handling. You generally don't need nested handling and all you really need to do is check for null and close the stream/client. That should be about the only try-catch block you need. Depending upon where in the process you want to recover determines where it goes but I'm thinking just the one try-catch in your HandleClientComm method. Using a using statement would dramatically clean up this code.

您可能还想了解一些C#的新功能。 Async / await可以稍微清理你的代码,这样你就不需要自己管理线程了。这取决于有多少"客户"。你希望有,但如果客户端是短期连接,你可能会使用Task来管理客户端。如果您的客户端连接到服务器然后保持连接很长一段时间,那么线程就可以了,但最终您应该考虑切换到线程
池,这样每个客户端都不会获得专用线程。这就是Web服务器的工作方式,但它会使代码复杂化。

You might also want to look into some newer features of C#. Async/await may be able to clean up your code a little bit such that you don't need to manage the thread yourself. It depends upon how many "clients" you expect to have but you could probably get away with using Task to manage the clients if clients are short-lived connections. If your clients connect to the server and then remain connected for extended lengths of time then threads would be OK but ultimately you should consider switching to a thread pool such that each client doesn't get a dedicated thread. This is how web servers work but it would complicate the code.

这是我对某些更改的初始传递,但由于我不理解或无法访问您的所有逻辑,我无法制作很多变化。

Here's my initial pass on some of the changes but since I don't understand or have access to all your logic I cannot make a lot of changes.

private void Server_Load ( object sender, EventArgs e )
{
    //If this call fails then the entire process should fail
    this.tcpListener = new TcpListener(IPAddress.Any, port);
    this.listenThread = new Thread(new ThreadStart(ListenForClients));
    this.listenThread.Start();            
}

private void ListenForClients ()
{
    tcpListener.Start();
    try
    {
        this.tcpListener.Start();
        while (true)
        {
            var client = this.tcpListener.AcceptTcpClient();
            ThreadPool.QueueUserWorkItem(new WaitCallback(HandleClientComm), client);
        }
    } catch (Exception ex)
    {
        //LogHelperISPL.Logger.Info("ListenForClients: " + ex.Message);               
    };

    this.tcpListener.Stop();            
}

private void HandleClientComm ( object data )
{            
    using (var client = data as TcpClient)
    {
        using (var clientStream = client.GetStream())
        {
            //Going to assume you're reading a string and that you want to read until the end, this would be
            //highly dependent upon the data you're receiving and make not work in your case. If it doesn't 
            //then use a buffered approach
            using (var reader = new StreamReader(clientStream))
            {
                var message = reader.ReadToEnd();

                //We'll use split here but it would be more efficient to simply use Span<T> if you're using the newest .NET/C# version
                //or at least IndexOf
                var tokens = message.Split(new[] { '!' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var token in tokens)
                {
                    var insertedRecord = ((token ?? "").Length >= 90) ? InsertRawData(token) : InsertRawDataGarbage(token);

                };
            };
        };                    
    };
}


这篇关于socket编程exe文件内存逐渐增加,socket也保持打开状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆