c# httpListner HELP

wpmanoj

Well-known member
  • Nov 18, 2010
    2,648
    6,412
    113
    C# HttpListner එක්ක ඒක්ස්පීරියන්ස් තියෙනවා නම් පොඩි හෙල්ප් ඒකක් දියල්ලා. කෝඩ් ඒක වැඩ ඒ්ත් මේකෙ මෙමරි ලීක් ඒකක් තියනවා. හැම රික්වෙස්ට් ඒකකටම පස්සෙ පොඩි ගානකින් රැම් ඒක පිරෙනවා ටිකින් ටික. කිලෝබයිට් ඒකක් දෙකක් වගේ. ඒ්ත් මේක දාන්න ඉන්න සිස්ටම් ඒකට දවසට රික්වෙස්ට් මිලියන ගානක් ඒනවා ඉතින් GB ගනනින් පිරෙන්න පුවවන්.

    මේකෙ වැරැද්දයි විසදුමක් පෙන්නල දියල්ලා.

    Code:
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Net;
    using System.Text;
    
    namespace __server
    {
        public class WebServer
        {
            private static HttpListener _listener;
            private static HttpListenerContext ctx;
            private static HttpListenerResponse response;
    
            public WebServer()
            {
                _listener = new HttpListener();
                _listener.Prefixes.Add("http://localhost:5010/");
                _listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
                _listener.Start();
    
                Console.WriteLine("Server Listening...");
            }
    
            public void Run()
            {
                while (_listener.IsListening)
                {
                    ctx = _listener.GetContext();
    
                    response = ctx.Response;
    
                    HttpListenerRequest request = ctx.Request;
                    SendResponse(200, "DONE");
                }
            }
    
            private static void SendResponse(int statusCode, string statusResponse)
            {
                byte[] buffer = Encoding.UTF8.GetBytes(statusResponse);
    
                response.ContentLength64 = buffer.Length;
                response.StatusCode = statusCode;
                response.StatusDescription = statusResponse;
    
                Stream output = response.OutputStream;
                output.Write(buffer, 0, buffer.Length);
                output.Close();
    
                response.Close();
            }
            
        }
    }
     

    HAneo

    Well-known member
  • Jan 30, 2007
    12,970
    29,168
    113
    Homagama
    WOW. at first glance what the fuck garbage collectors do here? but i trust your words
    Interesting Scenario
    I would love to see this if you give me today pls?

    C# HttpListner එක්ක ඒක්ස්පීරියන්ස් තියෙනවා නම් පොඩි හෙල්ප් ඒකක් දියල්ලා. කෝඩ් ඒක වැඩ ඒ්ත් මේකෙ මෙමරි ලීක් ඒකක් තියනවා. හැම රික්වෙස්ට් ඒකකටම පස්සෙ පොඩි ගානකින් රැම් ඒක පිරෙනවා ටිකින් ටික. කිලෝබයිට් ඒකක් දෙකක් වගේ. ඒ්ත් මේක දාන්න ඉන්න සිස්ටම් ඒකට දවසට රික්වෙස්ට් මිලියන ගානක් ඒනවා ඉතින් GB ගනනින් පිරෙන්න පුවවන්.

    මේකෙ වැරැද්දයි විසදුමක් පෙන්නල දියල්ලා.

    Code:
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Net;
    using System.Text;
    
    namespace __server
    {
        public class WebServer
        {
            private static HttpListener _listener;
            private static HttpListenerContext ctx;
            private static HttpListenerResponse response;
    
            public WebServer()
            {
                _listener = new HttpListener();
                _listener.Prefixes.Add("http://localhost:5010/");
                _listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
                _listener.Start();
    
                Console.WriteLine("Server Listening...");
            }
    
            public void Run()
            {
                while (_listener.IsListening)
                {
                    ctx = _listener.GetContext();
    
                    response = ctx.Response;
    
                    HttpListenerRequest request = ctx.Request;
                    SendResponse(200, "DONE");
                }
            }
    
            private static void SendResponse(int statusCode, string statusResponse)
            {
                byte[] buffer = Encoding.UTF8.GetBytes(statusResponse);
    
                response.ContentLength64 = buffer.Length;
                response.StatusCode = statusCode;
                response.StatusDescription = statusResponse;
    
                Stream output = response.OutputStream;
                output.Write(buffer, 0, buffer.Length);
                output.Close();
    
                response.Close();
            }
          
        }
    }

    SendResponse() needs to be non-static neda?
    Even if you got 1000 requests there is only one method of this will exists. this is not a good practice.

    even if you respond.Close(); variable buffer variable will not disposed

    The static variable of your class are not garbage collected until the app domain hosting your class is unloaded. The Dispose() method will not be called, because it is an instance method,

    Solution 1.
    clear buffer after you use it inside the method

    Solution 2.

    Make this static --> non-static so you will use classes/objects then it will dispose Autonomously by the GC
    ------ Post added on Aug 21, 2022 at 1:15 PM
     
    Last edited:
    • Like
    Reactions: wpmanoj

    wpmanoj

    Well-known member
  • Nov 18, 2010
    2,648
    6,412
    113
    tried both solutions but same result bro.

    Code:
    using System;
    using System.IO;
    using System.Net;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WindowsFormsApp1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
    
                new WebServer();
            }
        }
    
        public class WebServer
        {
            public WebServer()
            {
                HttpListener _listener = new HttpListener();
                _listener.Prefixes.Add("http://localhost:5010/");
                _listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
                _listener.Start();
    
                Console.WriteLine("Server Listening...");
    
                byte[] buffer = Encoding.UTF8.GetBytes("done");
    
                while (_listener.IsListening)
                {
                    HttpListenerResponse response = _listener.GetContext().Response;
                    response.ContentLength64 = buffer.Length;
                    response.StatusCode = 200;
    
                    Stream output = response.OutputStream;
                    output.Write(buffer, 0, buffer.Length);
                    output.Close();
                    response.Close();
                }
            }
    
        }
    }

    WOW. at first glance what the fuck garbage collectors do here? but i trust your words
    Interesting Scenario
    I would love to see this if you give me today pls?



    SendResponse() needs to be non-static neda?
    Even if you got 1000 requests there is only one method of this will exists. this is not a good practice.

    even if you respond.Close(); variable buffer variable will not disposed



    Solution 1.
    clear buffer after you use it inside the method

    Solution 2.

    Make this static --> non-static so you will use classes/objects then it will dispose Autonomously by the GC
    ------ Post added on Aug 21, 2022 at 1:15 PM
    ------ Post added on Aug 21, 2022 at 2:04 PM
     

    HAneo

    Well-known member
  • Jan 30, 2007
    12,970
    29,168
    113
    Homagama
    tried both solutions but same result bro.

    Code:
    using System;
    using System.IO;
    using System.Net;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WindowsFormsApp1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
    
                new WebServer();
            }
        }
    
        public class WebServer
        {
            public WebServer()
            {
                HttpListener _listener = new HttpListener();
                _listener.Prefixes.Add("http://localhost:5010/");
                _listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
                _listener.Start();
    
                Console.WriteLine("Server Listening...");
    
                byte[] buffer = Encoding.UTF8.GetBytes("done");
    
                while (_listener.IsListening)
                {
                    HttpListenerResponse response = _listener.GetContext().Response;
                    response.ContentLength64 = buffer.Length;
                    response.StatusCode = 200;
    
                    Stream output = response.OutputStream;
                    output.Write(buffer, 0, buffer.Length);
                    output.Close();
                    response.Close();
                }
            }
    
        }
    }


    ------ Post added on Aug 21, 2022 at 2:04 PM
    Then have to dig deeper. let's see
     
    • Like
    Reactions: wpmanoj

    Pitihum

    Well-known member
  • Nov 16, 2016
    1,294
    539
    113
    using (HttpListener _listener = new HttpListener())
    {
    _listener.Prefixes.Add("http://localhost:5010/");
    _listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
    _listener.Start();

    Console.WriteLine("Server Listening...");

    byte[] buffer = Encoding.UTF8.GetBytes("done");

    while (_listener.IsListening)
    {
    using (HttpListenerResponse response = _listener.GetContext().Response)
    {
    response.ContentLength64 = buffer.Length;
    response.StatusCode = 200;

    using (Stream output = response.OutputStream)
    {
    output.Write(buffer, 0, buffer.Length);
    output.Close();
    response.Close();
    }
    }
    }
    }
     

    wpmanoj

    Well-known member
  • Nov 18, 2010
    2,648
    6,412
    113
    in Debug

    using (HttpListener _listener = new HttpListener())
    {
    _listener.Prefixes.Add("http://localhost:5010/");
    _listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
    _listener.Start();

    Console.WriteLine("Server Listening...");

    byte[] buffer = Encoding.UTF8.GetBytes("done");

    while (_listener.IsListening)
    {
    using (HttpListenerResponse response = _listener.GetContext().Response)
    {
    response.ContentLength64 = buffer.Length;
    response.StatusCode = 200;

    using (Stream output = response.OutputStream)
    {
    output.Write(buffer, 0, buffer.Length);
    output.Close();
    response.Close();
    }
    }
    }
    }
    still memory increasing.
     

    HAneo

    Well-known member
  • Jan 30, 2007
    12,970
    29,168
    113
    Homagama
    @wpmanoj

    Ok, i did some modifications to the Code. removed the While Listening. and implement Callbacks. this way we don't have to wait for the requests but we will be notified upon the request hits the context.
    and it's Async Now. you can have multiple requests at the same time


    Code:
    public void NonblockingListener()
    {
            _listener = new HttpListener();
            _listener.Prefixes.Add("http://localhost/asynctest/");
            _listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
    
            _listener.Start();
            _listener.BeginGetContext(OnContext, null);
    
            Console.ReadLine();
     }

    Code:
       private void OnContext(IAsyncResult ar)
        {
            try
            {
                var guid = Guid.NewGuid();
                var ctx = _listener.EndGetContext(ar);
                _listener.BeginGetContext(OnContext, null);
    
                Console.WriteLine(DateTime.UtcNow.ToString("HH:mm:ss.fff") + " Handling request");
    
                var buf = Encoding.ASCII.GetBytes("Hello world - " + guid.ToString());
                ctx.Response.ContentType = "text/plain";
                ctx.Response.OutputStream.Write(buf, 0, buf.Length);
                ctx.Response.OutputStream.Close();
    
                Console.WriteLine(DateTime.UtcNow.ToString("HH:mm:ss.fff") + " completed");
            }
            catch (Exception ex)
            {
                Console.WriteLine(DateTime.UtcNow.ToString("HH:mm:ss.fff") + " Error " + ex.Message);
            }
        }

    Now even with this change, I couldn't stop the memory from increasing.
    See this.
    Mem-Profile1.png


    Then I analyze what has happened. you can see where the increase or decrease happens(analysis 2 snapshots and see the difference)

    Mem-Profile2.png


    So the Root of the problem is above 1 and 2. these both cause a memory leak. and as per the MS words, you cannot do anything about this. they always leaking a few Bytes per request. if logic gets complex this may leak from bytes to KB easily. you cannot do anything to this. because these are the .NET Runtime and OS API calls. both of them are in the Unmanaged stack which you or I never can access.

    Read these articles

    https://social.msdn.microsoft.com/F...-systemreflectionruntimemodule?forum=netfxbcl

    https://docs.microsoft.com/en-us/dotnet/core/diagnostics/debug-memory-leak
     

    wpmanoj

    Well-known member
  • Nov 18, 2010
    2,648
    6,412
    113
    @wpmanoj

    Ok, i did some modifications to the Code. removed the While Listening. and implement Callbacks. this way we don't have to wait for the requests but we will be notified upon the request hits the context.
    and it's Async Now. you can have multiple requests at the same time


    Code:
    public void NonblockingListener()
    {
            _listener = new HttpListener();
            _listener.Prefixes.Add("http://localhost/asynctest/");
            _listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
    
            _listener.Start();
            _listener.BeginGetContext(OnContext, null);
    
            Console.ReadLine();
     }

    Code:
       private void OnContext(IAsyncResult ar)
        {
            try
            {
                var guid = Guid.NewGuid();
                var ctx = _listener.EndGetContext(ar);
                _listener.BeginGetContext(OnContext, null);
    
                Console.WriteLine(DateTime.UtcNow.ToString("HH:mm:ss.fff") + " Handling request");
    
                var buf = Encoding.ASCII.GetBytes("Hello world - " + guid.ToString());
                ctx.Response.ContentType = "text/plain";
                ctx.Response.OutputStream.Write(buf, 0, buf.Length);
                ctx.Response.OutputStream.Close();
    
                Console.WriteLine(DateTime.UtcNow.ToString("HH:mm:ss.fff") + " completed");
            }
            catch (Exception ex)
            {
                Console.WriteLine(DateTime.UtcNow.ToString("HH:mm:ss.fff") + " Error " + ex.Message);
            }
        }

    Now even with this change, I couldn't stop the memory from increasing.
    See this.
    Mem-Profile1.png


    Then I analyze what has happened. you can see where the increase or decrease happens(analysis 2 snapshots and see the difference)

    Mem-Profile2.png


    So the Root of the problem is above 1 and 2. these both cause a memory leak. and as per the MS words, you cannot do anything about this. they always leaking a few Bytes per request. if logic gets complex this may leak from bytes to KB easily. you cannot do anything to this. because these are the .NET Runtime and OS API calls. both of them are in the Unmanaged stack which you or I never can access.

    Read these articles

    https://social.msdn.microsoft.com/F...-systemreflectionruntimemodule?forum=netfxbcl

    https://docs.microsoft.com/en-us/dotnet/core/diagnostics/debug-memory-leak
    oh really ! thanks bro.

    once i code a server (from stack overflow). it works like charm. unfortunately i missed that code. couldn't find stack overflow answer too. as i remember it has different approach.
     

    SLHodahitha

    Well-known member
  • Nov 8, 2017
    3,086
    2,975
    113
    ::0
    elakiri.com
    C#:
    [CODE=csharp]using System.Net;
    using System.Text;
    
    public class WebServer
    {
        private static HttpListener _listener;
        private static HttpListenerContext ctx;
        private static HttpListenerResponse response;
        private static byte[] buffer;
        public WebServer()
        {
            _listener = new HttpListener();
            _listener.Prefixes.Add("http://localhost:5010/");
            _listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
            _listener.Start();
    
            Console.WriteLine("Server Listening...");
        }
    
        public void Run()
        {
            while (_listener.IsListening)
            {
                ctx = _listener.GetContext();
    
                response = ctx.Response;
    
                HttpListenerRequest request = ctx.Request;
                SendResponse(200, "DONE");
            }
        }
        private static void SendResponse(int statusCode, string statusResponse)
        {
            buffer = Encoding.UTF8.GetBytes(statusResponse);
    
            response.ContentLength64 = buffer.Length;
            response.StatusCode = statusCode;
            response.StatusDescription = statusResponse;
    
            using(Stream output = response.OutputStream){
                output.Write(buffer, 0, buffer.Length);
                output.Close();
            }
            response.Close();
        }
    
    }
    public class Program
    {
        public static void Main(string[] args) {
            WebServer wb = new WebServer();
            wb.Run();
        }
    }
    [/CODE]
     
    • Like
    Reactions: wpmanoj

    wpmanoj

    Well-known member
  • Nov 18, 2010
    2,648
    6,412
    113
    C#:
    using System.Net;
    using System.Text;
    
    public class WebServer
    {
        private static HttpListener _listener;
        private static HttpListenerContext ctx;
        private static HttpListenerResponse response;
        private static byte[] buffer;
        public WebServer()
        {
            _listener = new HttpListener();
            _listener.Prefixes.Add("http://localhost:5010/");
            _listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
            _listener.Start();
    
            Console.WriteLine("Server Listening...");
        }
    
        public void Run()
        {
            while (_listener.IsListening)
            {
                ctx = _listener.GetContext();
    
                response = ctx.Response;
    
                HttpListenerRequest request = ctx.Request;
                SendResponse(200, "DONE");
            }
        }
        private static void SendResponse(int statusCode, string statusResponse)
        {
            buffer = Encoding.UTF8.GetBytes(statusResponse);
    
            response.ContentLength64 = buffer.Length;
            response.StatusCode = statusCode;
            response.StatusDescription = statusResponse;
    
            using(Stream output = response.OutputStream){
                output.Write(buffer, 0, buffer.Length);
                output.Close();
            }
            response.Close();
        }
    
    }
    public class Program
    {
        public static void Main(string[] args) {
            WebServer wb = new WebServer();
            wb.Run();
        }
    }
    still leaking brother
     
    • Like
    Reactions: SLHodahitha