HttpListener behaviour

I’ve an application running on FEZ Cobra II (G120) and it seems that HttpListener doesn’t work correctly as expected.


        void TcpThreadManager()
        {
            HttpListener listener = null; 
            Debug.Print("HttpListener starting ...");
            HttpListenerContext wctx = null;
            HttpListenerRequest req;
            //Program.LCD_Disp.PrintString(2, 0, "HttpListener started ...");
            Thread.Sleep(200);
            while (true)
            {
                // wait for call from client:
                try
                {
                    if (listener == null)
                    {
                        listener = new HttpListener("http", 80);
                        listener.MaximumResponseHeadersLength = 8192;
                    }
                    listener.Start(); // Why I need to Start() each loop ?
                    Debug.Print("HttpListener started ....");
                    wctx = listener.GetContext();
                    // got call:            
                    if (wctx == null ) 
                        continue;
                    req = wctx.Request;
                    Debug.Print("->wctx remote addr: " + req.RemoteEndPoint.Address.ToString());
                    wctx.Response.ContentType = "text/plain";
                    wctx.Response.SendChunked = false;
                    Debug.Print("URL: " + wctx.Request.RawUrl);                    
                }
                catch (SocketException sex)
                {
                    Debug.Print("HttpListener stopped and cleared ... thread end ! ->" + sex.Message );
                    if (listener != null)
                    {
                        listener.Stop();                        
                        listener.Close();
                        Thread.Sleep(300);
                        listener = null;
                    }
                    continue;
                }
                // Process request
                //ProcessHttpRequest(wctx); // multi threaded version
                HttpContextServiceThread(wctx); // single thread version service routine
                //listener.Stop();    <- get exception if I call Stop() (SocketException)
            }
        }


As you can see in the code, If I don’t call HttpListener.Start() after every service requested, the underlying socket crash after a while (may be till 10hours) and no way to recreate again the listener. If I call HttpListener.Stop() I get an exception, but Start() still work and listner comes up again correctly.
The code above works correctly and create no problem, although I think this is not the correct way to use HttpListner. On the MS framewk it’s not needed to close/open each service request.

The service request are like this:


        void HttpContextServiceThread(HttpListenerContext wctx)
        {
            Queue qTx, qRx;
            qTx = Program.qSmsTx;
            qRx = Program.qSmsRx;
            string _resp;
            HttpListenerRequest wreq = wctx.Request;
            string[] s = wreq.RawUrl.Trim().Split(new char[] { '?' });
            switch(s[0])
            {    
                case "/": 
                case "/test":
                    string ONLINE = "ONLINE";
                    wctx.Response.OutputStream.Write(Encoding.UTF8.GetBytes(ONLINE), 0, ONLINE.Length );
                    wctx.Response.Close();
                    break;
                case "/sms":
                    if (wctx.Request.HttpMethod == "POST")
                    {
                        //Program.GoSendSms = false;
                        // Get post messages
                        GetHttpPostSms(qRx, wctx.Request);                            
                    }                        
                    SendHttpResponse(qTx, wctx.Response);
                    Program.GoSendSms = true;
                    break;
                case "/status":
                    //DebugPrintHeaders(wctx);
                    if (wctx.Request.Headers["ServerDateTime"] != null)
                    {
                        string svrdate = wctx.Request.Headers["ServerDateTime"];
                        DateTime t = ParseInitDate(svrdate);
                        GHI.Premium.Hardware.RealTimeClock.SetTime(t);
                        Microsoft.SPOT.Hardware.Utility.SetLocalTime(t);
                    }
                    SendHttpInfoResponse(qRx.Count, qTx.Count, wctx.Response);
                    break;

...
//.... here there are other case...
...   
                  default:
                    wctx.Response.OutputStream.Write(new byte[] { 49 }, 0, 1);
                    wctx.Response.OutputStream.Close();
                    wctx.Response.Close();
                    break;
            }
        }


May be I’m doing something wrong …

???

It seems I got a solution. May be useful to others.

I used multithreaded version of service routine:


...
                ProcessHttpRequest(wctx); // threaded version
                //HttpContextServiceThread(wctx); // single version
                //listener.Close();    
            }
        }

        void ProcessHttpRequest(HttpListenerContext wctx)
        {
            Thread _servicethread = new Thread(
                delegate()
                {
                    HttpContextServiceThread(wctx);
                }
                );
            _servicethread.Start();
        }

Then I needed to lock() all the queue (Queue object) access code.
I’ve not digged very deep, but it seems that G120 board receive some dummy call from the network (PC browsers, servers or other appliance in the LAN) and in single thread mode it’s not serviced correctly sometimes. This let httplistener fall in a locked status.
Now the httplistener is up and running like a bjoux since 12 days …

:slight_smile:

Can you share a complete code…

Also can you please stress your code using this:
https://www.ghielectronics.com/community/codeshare/entry/780

And report back if it locks … and at what point…

Mine always locks at different points but never passes 100,000.00 calls…

Thank you for sharing…

Hi Jay Jay,
I will for sure test Cobra II network with the code in the link … I just remember to have done this test many monthes ago … but can’t remind results.
I’m sure it will lock at certain point.
My application is quite long, but I can simplify to show code. This app was written really in a hurry to show a proof-of-concept in SMS handling, so I decided to use HttpListener instead of standard sockets that I normally use. I discovered that HttpListener is an interesting and fast alternative solution for network comunication, specially if you want to use a browser to connect to the board.
The Cobra II is wrapped by a web service running on a Windows Server 2012 with SQLserver 2012, and It is isolated from outer world. Any comunication from outside world (applications) are arbitrated by window server through a web service api. This avoid haevy (and unkown) stress to the FEZ board. Actually the Cobra II handle 1sec round call from server, and it manages to callback the server when new SMS arrives. I tested the board with upto 2 real SMS/sec to a total of 120 sms and I got no issue (for now). But now I’m porting the app to a G400 board and I will make new tests. I’m writing this days a PC fwk program to make this tests.
In heavy stress condition, the HttpListener (but also socket) miserably fail and this happens also on the G400HDR, keeping in mind that I’ve done just an empirical test.

Hi,
First Thanks for the updates :)…

did you by any chance get around to stress testing your solution with the mention codeshare? how many pings did you get before it froze if it froze?

@ Jay Jay - I’m running the StressTestNetwork program by PhilM on a G400HDR V1.2 with ENC28.
I’ve no issue till 9000 bytes sent packet (0ms). Going up with size, I get lot of retry packet on the lan and at >13000 bytes it doesn’t work anymore.
If I go above 13000 then I can’t get no reliable response although I go below 9000 byte, needing a board reset.
Tell me if you need something more specific…

Thanks for the updates, so there is still issues with the Ethernet …

maybe GHI will be interested in your findings and code so they can fix the issue…