Main Site Documentation

Spider & Wifi SocketException


#1

I think this is not necessarily FEZ spider and Wifi issue, I think this might be in .NET MF but I’m not sure.

I have Spider connected to wifi. I have set up small http “server” on the board and I can connect it from PC and I get responses back nicely. I added camera in stream mode to take pictures so that I can show a picture also in the http page. If I post back the whole image, I get following exception

#### Exception System.Net.Sockets.SocketException - CLR_E_FAIL (1) ####
#### Message: 
#### Microsoft.SPOT.Net.SocketNative::send [IP: 0000] ####
#### System.Net.Sockets.Socket::Send [IP: 0018] ####
#### System.Net.Sockets.NetworkStream::Write [IP: 0051] ####
#### System.Net.OutputNetworkStreamWrapper::Write [IP: 0017] ####
#### GadgeteerApp2.Program::ProgramStarted [IP: 00ff] ####
#### GadgeteerApp2.Program::Main [IP: 0015] ####
#### SocketException ErrorCode = 10035

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

If I post only first 10000 bytes, it works. If I try first 20000 it fails again. So there has to be somekind buffer limit somewhere between 10000 and 20000? Or I’m doing something wrong?


HttpListener listener = new HttpListener("http");
        int hits = 0;
        Bitmap cameraBitmap = new Bitmap(160, 120);
        void ProgramStarted()
        {
            //WiFi.UpdateFirmware(WiFi.HardwareModule.RS9110_N_11_21_1_Compatible, SPI.SPI_module.SPI2, (Cpu.Pin)10, (Cpu.Pin)18, (Cpu.Pin)20);
            WiFi.Enable(WiFi.HardwareModule.RS9110_N_11_21_1_Compatible, SPI.SPI_module.SPI2, (Cpu.Pin)10, (Cpu.Pin)18, (Cpu.Pin)20);// FEZ Spider Socket 6
            WiFi.ConnectInfrastructure(new AccessPointInfo(0, SecurityMode.WEP, "default"), "********");

            NetworkInterface[] netif = NetworkInterface.GetAllNetworkInterfaces();
            netif[0].EnableDhcp();

            WriteLine("IP Address: " + netif[0].IPAddress, 10);
            WriteLine("Subnet Mask: " + netif[0].SubnetMask, 25);
            WriteLine("Default Getway: " + netif[0].GatewayAddress, 40);
            WriteLine("DNS Server: " + netif[0].DnsAddresses[0], 55);

            camera.CurrentPictureResolution = Gadgeteer.Modules.GHIElectronics.Camera.PictureResolution.Resolution160x120;
            camera.BitmapStreamed += new Camera.BitmapStreamedEventHandler(camera_BitmapStreamed);
            camera.StartStreamingBitmaps(cameraBitmap);
            listener.MaximumResponseHeadersLength = -1;
            listener.Start();

            while (true)
            {
                HttpListenerContext context = listener.GetContext();
                try
                {
                    if (context.Request.RawUrl.ToLower().IndexOf(".jpg") > 0)
                    {
                        lock (cameraBitmap)
                        {
                            Debug.GC(true);
                            byte[] data = cameraBitmap.GetBitmap();
                            context.Response.OutputStream.Write(data, 0, data.Length);
                            
                        }
                    }
                    else
                    {
                        hits++;
                        byte[] data = Encoding.UTF8.GetBytes(@ "
                        <html>
                            <body>
                                <h1>FEZ Spider here! Page has been viewed " + hits + @ " times.</h1>
                                <br>
                                <img src=""coffee.jpg""/>
                                <br>
                             </body>
                        </html>");
                        context.Response.OutputStream.Write(data, 0, data.Length);

                    }
                }

                catch (Exception e)
                {
                    WriteLine("Error! " + e.Message, 100);
                }
                context.Close();
            }

        }

        private void WriteLine(string text, uint y)
        {
            display.SimpleGraphics.DisplayText(text, Resources.GetFont(Resources.FontResources.small), Colors.White, 10, y);
        }

        void camera_BitmapStreamed(Camera sender, Bitmap bitmap)
        {
            lock (cameraBitmap)
            {
                cameraBitmap = bitmap;
            }

        }

PS. I don’t know why the code tag doesn’t work
PS2. Does the WIFI support WPA2 with EAP-PEAP


#2

try sending the message in pieces instead of all at once. it is an internal buffer size issue.


#3

I actually tried that. I split it to 10000 chunks but still the same error in second interation. I called the OutputStream.Flush after each iteration.


#4

Please use code tags so your code is readable.


#5

Code tag seems broken ???

Method ThisIsCode
{
  int i=20;
}

#6

Second report of ‘black friday’ busted code tag…


#7

Looks like they are fixed now.


#8

the ProgramStarted() method should only be used for initialization.

Try putting you code into a thread.


#9

Still doesn’t work. Now the listener is running in own thread and data is split to 1024 size chunks. I also removed the camera from the equation and I’m using resource image instead (6,7 KB). In my tests the interation fails randomly between 4-10 interations but usually it is either 4 or 5.


        HttpListener listener = new HttpListener("http");
        int hits = 0;
        Dispatcher d;
        void ProgramStarted()
        {
            //WiFi.UpdateFirmware(WiFi.HardwareModule.RS9110_N_11_21_1_Compatible, SPI.SPI_module.SPI2, (Cpu.Pin)10, (Cpu.Pin)18, (Cpu.Pin)20);
            WiFi.Enable(WiFi.HardwareModule.RS9110_N_11_21_1_Compatible, SPI.SPI_module.SPI2, (Cpu.Pin)10, (Cpu.Pin)18, (Cpu.Pin)20);// FEZ Spider Socket 6
            WiFi.ConnectInfrastructure(new AccessPointInfo(0, SecurityMode.WEP, "default"), "**********");
            d = Dispatcher.CurrentDispatcher;

            NetworkInterface[] netif = NetworkInterface.GetAllNetworkInterfaces();
            netif[0].EnableDhcp();

            WriteLine("IP Address: " + netif[0].IPAddress, 10);
            WriteLine("Subnet Mask: " + netif[0].SubnetMask, 25);
            WriteLine("Default Getway: " + netif[0].GatewayAddress, 40);
            WriteLine("DNS Server: " + netif[0].DnsAddresses[0], 55);

            Thread thread = new Thread(new ThreadStart(RunServer));
            thread.Start();

        }

        private void RunServer()
        {
            listener.MaximumResponseHeadersLength = -1;
            listener.Start();
            while (true)
            {

                HttpListenerContext context = listener.GetContext();
                int counter = 0;
                try
                {
                    if (context.Request.RawUrl.ToLower().IndexOf(".jpg") > 0)
                    {
                        byte[] data = Resources.GetBitmap(Resources.BitmapResources.flag_finland).GetBitmap();
                        context.Response.SendChunked = true;

                        for (int i = 0; i < data.Length; i = i + 1024)
                        {
                            counter++;
                            if (data.Length - i < 1024)
                                context.Response.OutputStream.Write(data, i, data.Length - i);
                            else
                                context.Response.OutputStream.Write(data, i, 1024);
                            context.Response.OutputStream.Flush();
                        }
                    }
                    else
                    {
                        hits++;
                        byte[] data = Encoding.UTF8.GetBytes(@ "
                        <html>
                            <body>
                                <h1>FEZ Spider here! Page has been viewed " + hits + @ " times.</h1>
                                <br>
                                <img src=""coffee.jpg""/>
                                <br>
                             </body>
                        </html>");
                        context.Response.OutputStream.Write(data, 0, data.Length);
                    }
                }
                catch (Exception e)
                {
                    WriteLine("Error in counter " + counter.ToString() + "! " + e.Message, 100 + (uint)hits*10);
                }
                context.Close();
            }
        }

        private void WriteLine(string text, uint y)
        {
            d.Invoke(new TimeSpan(0, 0, 10), o =>
            {
                display.SimpleGraphics.DisplayText(text, Resources.GetFont(Resources.FontResources.small), Colors.White, 10, y);
                return null;
            }, null);
        }


#10

You may be working the GC too hard…
Try this:

  1. create a separate HttpServer class and instantiate it once from ProgramStarted()
  2. in the HttpServerclass constructor acquire the bitmap [italic]once[/italic] and assign it to a class-global variable

#11

Actually, in [italic]actually reading[/italic] your error codes (10035; explained here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx), it seems that you may benefit from inserting some delays in your loop.

'WSA_BOULD_BLOCK" is not necessarily a failure state, since it indicates that non-blocking sockets are in use, but the most recent call cannot be completed due to a socket operation already in progress.

You should still take the actual “working code” out of the ProgramStarted() method as I indicated before.


#12

It is running on a thread already so it is running out of the ProgramStarted. I have also found that Microsoft post and tried delays without success. I tested it again with same results.

With HttpWebRequest I cand post the pictures to my site so the network is working fine. And there I can post the whole picture without splitting the byte[]. So there has to be some issues with HttpListener.Response.


#13

Whether you use one or several threads is not the issue.
As noted in the article I linked, that error code indicates that you’re asking Net.Sockets to respond faster than it is currently able.
From the article:

[quote]This error is returned from operations on nonblocking sockets that cannot be completed immediately, for example recv when no data is queued to be read from the socket. It is a nonfatal error, and the operation should be retried later[/quote].

I’ts not a “bug” as such; jsut that you’re asking more of Net.Sockets than it’s curently able to satisfy.


#14

Jimmy, thank you for trying to help but I don’t still buy that one ;). Yes, in the beginning I was asking too much from the socket but now I’m sending 1 KB in 500 ms, I don’t think that is too much asked from the socket?

Also if I’m the client and sending the data with HttpWebRequest, why does the socket accept my “payload” in one go ~50KB?


   context.Response.OutputStream.WriteTimeout = 1000000;
                        context.Response.OutputStream.ReadTimeout = 1000000;

                        for (int i = 0; i < bmp.Length; i = i + 1024)
                        {
                            
                            counter++;
                            if (bmp.Length - i < 1024)
                                context.Response.OutputStream.Write(bmp, i, bmp.Length - i);
                            else
                                context.Response.OutputStream.Write(bmp, i, 1024);
                            context.Response.OutputStream.Flush();
                            Thread.Sleep(500);
                        }


#15

I have good news and bad news…

I was able to repro a similar error.
I have something for you to try:
[ol]Obtain your favorite network capture tool (http://www.tcpdump.org/, http://www.wireshark.org/, http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=4865).
Install said tool on the target host
Start the tool capturing packets
Start your NetMF application[/ol]

…when you get your repro, examine the capture. Does it indicate a connection failure state (SYN packets from your Spider, but no answering SYN-ACK)?

What I discovered in my own app development (reworking the Gadgeteer WPAD tester) was that if the target of a System.Net.WebRequest.GetResponse() call failed to accept the TCP connection, I would receive the same “System.Net.Sockets.SocketException (10035)” that you’re reporting.

The error code that should have been reported in my case is 10060 “WSAETIMEDOUT”, not 10035. Although it’s “not completely incorrect” to report 10035 (because a connection timeout [italic]would[/italic] block the sockets call), it’s more accurate (not to mention “helpful”) to report the proper error code.

I’ve filed http://netmf.codeplex.com/workitem/1392 with the Gadgeteer team for this issue.


#16

Thanks Jimmy. I will test that and report results, unfortunately it goes to next week.