none
socket programming exe file memory increasing gradually and also socket remain open RRS feed

  • Question

  • 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

    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();
        }
     }
    }

    Wednesday, June 13, 2018 9:37 AM

All replies

  • 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? 

    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.

    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. 

    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.

    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);
    
                    };
                };
            };                    
        };
    }


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, June 13, 2018 2:28 PM
    Moderator
  • First Thank you sir for givening replay.

    What file? --> I am talking about .exe file as mention on top of code

    Are you talking about the amount of memory your program is using?  --> No i am not store data and not my program is take that much of memory

    Are you really wanting to limit the data to 4K? --> No

    I am using your HandleClientComm function it's work properly and it's help full to me.

    In my application data come from multiclent around 900 and in 10 second each client send me a string means in 10 second i get 900 string from client. actually i am open connection for each client to take string from client but i do't have idea how can i mange client connection so every time connectio open and after read string from client that connection is close. That i have to do 900 time in 10 second.

    can you help me. How can manage client connection so no. of open port close after read string from client every time and for each and every client

    I have done client connection code in ListenForClients and   Server_Load 

    Thursday, June 14, 2018 6:55 AM
  • "I am talking about .exe file as mention on top of code"

    An EXE only takes up the amount of space of the compiled code. The amount of data you have has no impact on the EXE file size. While your app is running the memory used for your app would go up as you allocate memory. This is normal for a .NET app until you cross the minimum memory threshold that .NET uses. After that memory should level off unless you are doing something heavy. Given your 10 second interval I could see an increase in memory every 10 seconds but it should drop back down after a while. The GC in .NET runs at specific locations so you may see memory going up for a while. But at some point it'll drop back down.

    " but i do't have idea how can i mange client connection so every time connectio open and after read string from client that connection is close"

    The code I posted does that. Using the using statement, it opens the client, gets the stream and then reads the data. After that it cleans up all 3 resources. The only memory leak that would occur here is memory you allocate and hold on to after the method ends (whatever your InsertRawData functions are doing).

    Please use my test code and confirm that the memory is staying pretty steady over time. You should see an increase whenever the clients connect but it should drop back down later.



    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, June 14, 2018 1:47 PM
    Moderator