Main Site Documentation

Web Server Problem


#1

I’m trying to implement a Web Server and have had mixed results. I have an Arduino Ethernet Shield mounted to my FEz Panda II. I have wired SPI1 to the ICSP connector and have watched the SPI data on a logic analyzer. A variation of the code below worked at one point and then I modified as it appears below. Now neither version of the code results in the expected browser response. I’m using IE 8 and getting the error that it “can’t display the web page.” The Debug output looks like this:

***************** Debug output below *********

GET / HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, /
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E)
Accept-Encoding: gzip, deflate
Host: 192.168.0.177
Connection: Keep-Alive

************** Response **************
HTTP/1.1 200 OK
Content-Type: text/html
Connection: close

Scott's Server Test 2
Counter=33

Which seems to show I’m getting the request and sending what I think is a proper reply. I can see that the response buffer is being sent to the W5100 on the logic analyzer.

Anyone see any problems with my code?

**************** Code **************************


using System;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Net;
using GHIElectronics.NETMF.Net.Sockets;
using GHIElectronics.NETMF.Net.NetworkInformation;
using System.Text;

namespace FPII_Web_Srvr
{
    public class Program
    {
        static OutputPort p1 = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.An0, false);
        static int ctr = 0;
        static OutputPort led = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.LED, false);


        public static void Main()
        {

            bool ledState = false;
            Thread ProcHttp = new Thread(ProcessRequest);

            ProcHttp.Start();

            while (true)
            {
                // Sleep for 500 milliseconds
                Thread.Sleep(1000);

                // toggle LED state
                ledState = !ledState;
                led.Write(ledState);

                ctr++;
                if (ctr>2000) ctr=0;

            }
        }

        static void ProcessRequest()
        {
            while (true)
            {
                const Int32 c_port = 80;
                byte[] ip = { 192, 168, 0, 177 };
                byte[] subnet = { 255, 255, 255, 0 };
                byte[] gateway = { 192, 168, 0, 1 };
                byte[] mac = { 43, 185, 44, 2, 206, 127 };
                const Int32 c_microsecondsPerSecond = 1000000;

                p1.Write(true);

                WIZnet_W5100.Enable(SPI.SPI_module.SPI1, (Cpu.Pin)FEZ_Pin.Digital.Di10,
                (Cpu.Pin)FEZ_Pin.Digital.Di7, true);

                p1.Write(false);

                NetworkInterface.EnableStaticIP(ip, subnet, gateway, mac);
                NetworkInterface.EnableStaticDns(new byte[] { 192, 168, 0, 1 });

                p1.Write(true);

                Socket server = new Socket(AddressFamily.InterNetwork,
                            SocketType.Stream, ProtocolType.Tcp);

                p1.Write(false);

                IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, c_port);
                server.Bind(localEndPoint);
                server.Listen(1);

                p1.Write(true);
                while (true)
                {
                    // Wait for a client to connect.
                    Socket clientSocket = server.Accept();

                    // 'using' ensures that the client's socket gets closed.
                    using (clientSocket)
                    {
                        // Wait for the client request to start to arrive.
                        Byte[] buffer = new Byte[1024];
                        if (clientSocket.Poll(5 * c_microsecondsPerSecond,
                        SelectMode.SelectRead))
                        {
                            // If 0 bytes in buffer, then the connection has been closed,
                            // reset, or terminated.
                            if (clientSocket.Available == 0)
                                return;
                            // Read the first chunk of the request (we don't actually do
                            // anything with it).
                            Int32 bytesRead = clientSocket.Receive(buffer,
                                        clientSocket.Available, SocketFlags.None);

                            Debug.Print(new String(Encoding.UTF8.GetChars(buffer)));

                            // Return a static HTML document to the client.
                            String s =
                            "HTTP/1.1 200 OK\r\n" +
                            "Content-Type: text/html\r\n" +
//                        charset=utf-8\r\n" +
                            "Connection: close\r\n" +
//                        "Refresh: 5\r\n" +
                            "<!DOCTYPE HTML>\r\n" +
                            "<html>\r\n" +
                            "Scott's Server Test 2<br />\r\n" +
                            "Counter=" + ctr.ToString() + "<br />\r\n" +
                            "</html>\r\n";

                            Debug.Print("************** Response **************");
                            Debug.Print(s);
                            Debug.Print("**************************************");

                            byte[] buf = Encoding.UTF8.GetBytes(s);
                            int offset = 0;
                            int ret = 0;
                            int len = buf.Length;

                            p1.Write(false);

                            while (len > 0)
                            {
                                ret = clientSocket.Send(buf, offset, len, SocketFlags.None);
                                len -= ret;
                                offset += ret;
                            }

                            p1.Write(true);
                            
                            clientSocket.Close();
                        }
                    }
                }
            }
        }
    }
}


#2

Using code tags will make your post more readable. This can be done in two ways:[ol]
Click the “101010” icon and paste your code between the

 tags or...
Select the code within your post and click the "101010" icon.[/ol]
(Generated by QuickReply)

#3

your code tagging didn’t work properly - edit your post and fix that up (it’s surprising how much more readable it is then!)

When it comes to coding for this, I always go back to the Fez Connect codeshare projects https://www.ghielectronics.com/community/codeshare/entry/363 by jasdev and https://www.ghielectronics.com/community/codeshare/entry/247 by Nicolas3 as great references to benchmark your code against


#4

yes you can edit the post. There’s a set of icons up at the top right of each post that look greyed out, but isn’t, and one looks like a pencil. Click, highlight your old text, click the top 101010 button, and then submit.

Suggestion to your problem at hand.

First, I would move the Wiz5100 setup and initialisation code out of ProcessRequest(). Put it back in Main() before you start your thread. (even the naming of these imply that’s what you meant to do)

Second, can you confirm what the actual error is that the browser returns?You might need to click the

Third, use Netmon to capture the actual communication between the PC and the device. Install from here http://www.microsoft.com/en-us/download/details.aspx?id=4865 onto the PC that you’re browsing from. That’s a great way to see exactly what comes back, if anything.


#5

Thank you all.

I took Brett’s first comment and edited the original post.

I cleaned up the code as Brett suggested but it didn’t change anything the response.

I’m intrigued by his second comment regarding browser error returns that ends in “You might need to click the…” I’d like to know what to click to get browser error codes?

I’m going to pursue the third suggestion next (Netmon). The example code he referenced earlier I glanced at but they appear to be much more complicated approaches and I’d like to get this simple one working if possible as a starting point. A variation of it did work previously.


#6

I’m using NetMon and trying to figure out what the difference is between the little Arduino Server that works fine and the one I’m running on the Fez Panda II using the same Ardiuno Ethernet Shield.

I can’t see any real difference in the actual content I’m sending but the Arduino sends a bunch of HTTP packets and on the Fez I’m sending one packet.

This is the content I’m sending:

HTTP/1.1 200 OK
Content-Type: text/html
Connection: close

Scott's Server Test 1
Counter=3

Not sure what I’ll try next. Either sending each line one at a time or tweaking the html fearing I have some stupid error in that.


#7

First of ail, do not Forget that if you want things to appear, you need to put them between …


#8

The missing bit was something like the “click for more information” message, so you can see the actual HTTP error message. Something like whether it says it can’t find the DNS or a 404 error or exactly what…

Can you share with us the firmware version on your device? 4.1.x… I happen to have my Panda+Ethernet sitting close to hand and I could potentially give it a try for you but I wouldn’t want to try on a different version.


#9

Below are a number of lines from MFDeploy. Is that the version info you need?

HalSystemInfo.systemSerialNumber:
ClrInfo.clrVersion: 4.1.2821.0
ClrInfo.clrVendorInfo: Microsoft Copyright © Microsoft Corporation. All rig
ClrInfo.targetFrameworkVersion: 4.1.2821.0
SolutionReleaseInfo.solutionVersion: 4.1.8.0
SolutionReleaseInfo.solutionVendorInfo: GHI Electronics, LLC
SoftwareVersion.BuildDate: Dec 22 2011
SoftwareVersion.CompilerVersion: 410561

I added the … stuff just to make sure although it’s not present in the working Arduino code. Didn’t help.

I tweaked the Arduino code so it produced just two HTTP packets that look virtually identical to the two packets I now produce with the Fez. But the Arduino displays fine and nothings show with the Fez. When I use Firefox as the browser it indicates “The connection was reset. The connection to the server was reset while the page was loading.” I notice that the successful Arduino page has several TCP packets (to my address) following it while the Fez has only one.

I’d be glad to supply code.


#10

brett at brettpound dot com will get me… send me your project if you’re happy to share it? Otherwise just post the latest code here.


#11

sa319 - Just guessing, but you might be closing the socket too early.

Try putting a Thread.Sleep(1000) after the Write:


                            while (len > 0)
                            {
                                ret = clientSocket.Send(buf, offset, len, SocketFlags.None);
                                len -= ret;
                                offset += ret;
                            }
 
                            p1.Write(true);

                            Thread.Sleep(1000);
 
                            clientSocket.Close();


#12

Latest observations:

Working Arduino Web Server

I’ve seen some weird stuff here but it always works. I have split the response into several packets in various ways. The last approach I changed the code with the intent of sending one reply packet with the following Arduino code:


          os=String(String("HTTP/1.1 200 OK\nContent-Type: text/html\n")+
                String("Connection: close\n\n<!DOCTYPE HTML><html>")+
                "Scott's Server Test "+String(ctr)+"<br />"+
                "test another line3<br /></html>");

          client.print(os);                    

Apparently as a result of the use of strings the client.print function sent every character individually in it’s separate html packet. This didn’t cause any problem with the browser receiving and displaying the results properly.

Working with the Fez

I have pored through the data as sent to the W5100 on my logic analyzer and one difference that I observe is regarding the use of W5100 Sockets of which there are four on the chip. On the Arduino a single socket is used for reception of the html request and then subsequent transmission of my response. I think the Fez library code switches Sockets. After receiving the request on one socket it switches to another to send the reply. I’m not sure how this is managed inside the W5100 but I don’t see any way to control that in my code.

Oh and I tried various delays before closing the Socket. The working Arduino code closes it after a millisecond.


#13

I was wrong. In both cases, Arduino and Fez, 2 sockets are used. One is LISTENING. Then when a connection is established the other socket is set for LISTENING while the ESTABLISHED connection is used to complete the current transactions.


#14

Problem solved! There was something wrong with the MAC address. I started with an example on the web and apparently the MAC address in that example clashes with something on my system.