HttpListener startup failed after network cable is reconnected

I have written a very simple web server using the HttpListener class. I works well when I test it using my browser.

The problem is when I pull the network cable and then reconnect it to the board again. I always get the following error when I try to restart the HttpListener, I get the following error:

A first chance exception of type ‘System.Net.Sockets.SocketException’ occurred in Microsoft.SPOT.Net.dll
#### SocketException ErrorCode = 10048
#### SocketException ErrorCode = 10048

This looks like the port 80 is still in use, but I have no idea how to free the port, so that I can use it again.

When I don’t make any requests from the browser before I pull the canble, the restart works fine.

The board I use is the Spider II and I have installed the latest firmware and SDK.

This is the code I use:


static void NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
{
   if (e.IsAvailable)
   {
        server_running = true;

        httpThread = new Thread(RunServer);
        httpThread.Start();
    }
    else
    {
        server_running = false;
    }
}

private static void ProcessClientGetRequest(HttpListenerContext context)
{
    HttpListenerResponse response = context.Response;

    if (response != null)
    {
        response.StatusCode = (int)HttpStatusCode.OK;

        Debug.Print("URL: " + context.Request.RawUrl);

        string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
        byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
        // Get a response stream and write the response to it.
        response.ContentLength64 = buffer.Length;
        System.IO.Stream output = response.OutputStream;
        output.Write(buffer, 0, buffer.Length);

        output.Close();
        response.Close();
    }
 }

 internal static void RunServer()
 {
      HttpListener listener = new HttpListener("http");
      int tries = 50;
      bool is_started = false;

      while ((tries > 0) && (!is_started))
      try
      {
           listener.Start();
           is_started = true;
      }
      catch
      {
           tries -= 1;
           Thread.Sleep(1000);
       }

       if (is_started)
       {
           Mainboard.SetDebugLED(true);

          Debug.Print("HTTPListener is up and running");

          while (server_running)
          {
               HttpListenerContext context = null;

               try
               {
                   context = listener.GetContext();

                   if (context != null)
                   {
                       HttpListenerRequest request = context.Request;
                       if (request.HttpMethod.ToUpper() == "GET")
                       {
                           ProcessClientGetRequest(context);
                       }
                  }
                  else
                  {
                      Debug.Print("Gut null context. Closing Server down");

                      server_running = false;
                   }
               }
               catch
               {
                   Debug.Print("Listener Exception");
               }

               if (context != null)
               {
                   context.Close();
                   context = null;
               }
          }
     }
     else
     {
          Debug.Print("Too many retry attemps. Giving up");
     }

     listener.Stop();
     listener.Close();

     Mainboard.SetDebugLED(false);
}

Where are you handling network change events ? That’s where you’ll need to recycle your runserver thread on state changes. You could also try a try/catch block to catch the exception and restart the listener. If you haven’t done so, there’s numerous codeshare examples using http listener and you can get some tips there.

The network state change is handled in the NetworkAvailabilityChanged function at the beginning of the code block I posted.

I’m starting a new thread when the network comes up again and end it when the network becomes unavailable.

I went through some examples I have found in codeshare and in the forum.

The listening socket is not freed and this is why the #### SocketException ErrorCode = 10048 hannpens. Probably something isn’t closed properly, but I don’t know where.

OK yeah sure, I didn’t spot that. You handle the becoming available part of it, but not the unavailable scenario? If it was running and you then you lose connectivity, you only set server_running to false but don’t actually stop it.

What about if the IP address hasn’t become valid - you should also use the network address change event as well, don’t start the server until that’s non-zero (check the networking docs for simple examples of the check).

I’d also use lock around your state variables so you can’t get into a state where you start/stop things before everything is ready.

I found that listener.GetContext(); returns null context when the network becomes unavailable, so it wasn’t necessary to handle the available = false in the NetworkAvailabilityChanged.

This is nearly he whole program. The rest is just initialisation of the network, so there isn’t any other state handling or other network usage.

I’m using a fixed network address for this because I had problems getting an IP address using DHCP. The network address change callback doesn’t get called in this case.

I try to restart the listener 50 times wit one second wait, so that should give it enought time in any case.

Using the patches for the System.http packages also fixes this problem. With these fixes the listener can be restarted without any problem.

:-[ I can’t find httplistener?

I’ve included the following?

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT.Hardware;
using Microsoft.SPOT;
using Microsoft.SPOT.Net;
using Microsoft.SPOT.Net.NetworkInformation;

using GHI.Pins;
using GHI.Networking;

Thanks. When you start out learning this stuff, You really need to swallow your pride.

1 Like