SocketException during StartLocalServer (Hydra/ENC28) unless there's a delay

I’m getting a System.Net.Sockets.SocketException whenever I call WebServer.StartLocalServer. However, if I set a breakpoint on the StartLocalServer call and continue when it hits the breakpoint, or if I insert a sleep just before the StartLocalSever call (2270ms or more), the exception does not occur.

Here is the ProgramStarted code:


void ProgramStarted()
{
    Debug.Print("Program Started");
    ethernetENC28.UseThisNetworkInterface();
    ethernetENC28.UseStaticIP("192.168.0.2", "255.255.255.0", "192.168.0.1", new string[] { "8.8.8.8" });
    ethernetENC28.NetworkUp += ethernetENC28_NetworkUp;
    ethernetENC28.NetworkDown += ethernetENC28_NetworkDown;
}

Here is the NetworkUp event handler code:


void ethernetENC28_NetworkUp(GTM.Module.NetworkModule sender, GTM.Module.NetworkModule.NetworkState state)
{
    Debug.Print("Network is UP.");
    Debug.Print(ethernetENC28.NetworkSettings.IPAddress);          
    Debug.Print("SetUpWebEvent and assign handler");
    WebServer.SetupWebEvent("c").WebEventReceived += webEvent_WebEventReceived;
     WebServer.DefaultEvent.WebEventReceived += DefaultEvent_WebEventReceived;
     //Debug.Print("Sleeping...");
     //Thread.Sleep(2270);  // this delay (or higher) will prevent the exception.
     Debug.Print("Start web server");
     WebServer.StartLocalServer(ethernetENC28.NetworkSettings.IPAddress, 80);
     Debug.Print("Leaving NetworkUp handler.");
}

Here is the output if I do NOT set a breakpoint or introduce a delay before the StartLocalServer call:

Program Started
Network is UP.
192.168.0.2
SetUpWebEvent and assign handler
Start web server
#### Exception System.Net.Sockets.SocketException - CLR_E_FAIL (1) ####
#### Message:
#### Microsoft.SPOT.Net.SocketNative::bind [IP: 0000] ####
#### System.Net.Sockets.Socket::Bind [IP: 0016] ####
#### Gadgeteer.Networking.WebServerManager+Server::StartLocal [IP: 002d] ####
#### Gadgeteer.Networking.WebServerManager::StartServer [IP: 0012] ####
#### Gadgeteer.Networking.WebServer::StartLocalServer [IP: 0014] ####
#### HydraTest002.Program::ethernetENC28_NetworkUp [IP: 0062] ####
#### System.Reflection.MethodBase::Invoke [IP: 0000] ####
#### Gadgeteer.Program::DoOperation [IP: 001a] ####
#### Microsoft.SPOT.Dispatcher::PushFrameImpl [IP: 0054] ####
#### Microsoft.SPOT.Dispatcher::PushFrame [IP: 001a] ####
#### Microsoft.SPOT.Dispatcher::Run [IP: 0006] ####
#### Gadgeteer.Program::Run [IP: 001d] ####
#### SocketException ErrorCode = 10022
#### SocketException ErrorCode = 10022
A first chance exception of type ‘System.Net.Sockets.SocketException’ occurred in Microsoft.SPOT.Net.dll
#### SocketException ErrorCode = 10022
#### SocketException ErrorCode = 10022

Here is the output if I DO set/continue a breakpoint or introduce a delay of 2270ms or more:

Program Started
Network is UP.
192.168.0.2
SetUpWebEvent and assign handler
Sleeping…
Start web server
Web server started at http://192.168.0.2:80/
Leaving NetworkUp handler.

Running 4.3.6.0. The ENC28 is on socket 3 of the Hydra. Note that I can successfully ping 192.168.0.2 (the address of the Gadgeteer device) from another computer on the network.

ADDED NOTE: I just tried the same thing on a Spider with a J11D Ethernet module, and am getting the exact same results. Same exception when there’s no breakpoint or delay, but the exception disappears when I break/continue at the StartLocalServer call or introduce enough of a delay before the call.

Any thoughts on what’s happening here? I’m sure I must be missing something simple.

Thanks.

Before starting the web server I would make sure you actually have an IP address assigned.The current Gadgeteer code calls the NetworkUp handler before the address is actually set.

When the NetworkUp event occurs, I would start a thread, and keep checking the NetworkInterface object of ethernetENC28 object and wait until the IP address is not “0.0.0.0”. Then I would start the web server.

It is a timing issue, which explains why it works if you set a breakpoint.

1 Like

@ Mike -

Understood. I thought the fact that I was successfully printing the IP address from NetworkSettings before starting the server meant that the IP was assigned. Lesson learned. I will follow your recommendation. Thanks.

ethernetENC28 is a wrapper around a NetworkInface object. ethernetENC28 stored the static IP address and passed it to the interface object for initialization. After background initialization, the IP address gets set in the interface object.

The best way to understand how things work, or not work, is study the Gadgeteer source for the module.

There is also an IP address change event, which you would expect to indicate that the IP address is ready. I am not sure if it works correctly.

I usually put all of the network initialization into a separate thread and wait for the address there.

1 Like

@ Mike -

Thanks for the additional information.

After some additional experimentation, what I’m seeing is the NetworkInterface IP address is set to the correct address roughly two second before I can start the WebServer successfully. So, in my separate thread, I’m looking for that NetworkInterface IP address to be set correctly, and then I still have to sleep for a couple seconds if I want the StartLocatServer to succeed without getting this exception.

For now, doing the check for the NetworkInterface IP setting and then sleeping some additional time works for my particular application. When I get some time down the road, I’ll dig through the WebServer code to see if I can figure out exactly what it needs that isn’t there when I call it without the added delay.

@ kgcode - the issue is not in the web server. it is in the gadgeteer network code.

1 Like

@ Mike -

Okay, thanks. I misunderstood.