Main Site Documentation

Web Server - listener error


#1

( FEZ Domino with ‘W5100’ )

Hello , I´m using the code ‘W5100_HttpServer’ I found in ‘Tinyclr Wiki’, but I´m getting an error in the RunServer procedure [ listener.start() ] -> An unhandled exception of type ‘System.NotSupportedException ocurred in System.dll’ .

The hardware is well configured.

Any body knows the cause for this problem ?
Thanks


#2

Are you using the project as is? On what board are you trying it?


#3

I´m using a Fez Domino with an Wiznet ethernet shield; the hardware is well initialized because I can run othrer applications that use comunications at socket level; I do not understand why the ‘listener.start’ method fails with the System.dll error,
Thanks

More info … in the output windows:

The thread ‘’ (0x2) has exited with code 0 (0x0).
Network settings:
IP Address: 192.168.0.200
Subnet Mask: 255.255.255.0
Default Getway: 192.168.0.1
DNS Server: 192.168.0.1
#### Exception System.NotSupportedException - CLR_E_NOT_SUPPORTED (5) ####
#### Message:
#### System.Net.Sockets.Socket::.ctor [IP: 001f] ####
#### System.Net.HttpListener::Start [IP: 0020] ####
#### HttpServerSample.MyHttpServer::RunServer [IP: 000b] ####
#### HttpServerSample.MyHttpServer+PrefixKeeper::RunServerDelegate [IP: 0008] ####
A first chance exception of type ‘System.NotSupportedException’ occurred in System.dll
An unhandled exception of type ‘System.NotSupportedException’ occurred in System.dll


#4

I think you have the wrong assemblies included in your project. You are using NETMF standard ones those work on large devices) instead of using GHI’s (made for USBizi) http://wiki.tinyclr.com/index.php?title=Networking#USBizi_Network_Support


#5

Yes, I also think that is the problem; the question is wich are the ones I need; I do not find any reference to the httplistener ( System.Htp.dll ) in the link you sent me.

Here is the code: (in bold the place where the error happens) … thanks for your help …
//
using Microsoft.SPOT;
using Microsoft.SPOT.IO;
using Microsoft.SPOT.Hardware;

using System;
using System.Resources;
using System.Reflection;
using System.Text;
using System.Threading;
using System.IO;
using System.Net;

using GHIElectronics.NETMF.IO;
using GHIElectronics.NETMF.Net;
using GHIElectronics.NETMF.Net.NetworkInformation;
using GHIElectronics.NETMF.FEZ;

namespace HttpServerSample
{

public static class MyHttpServer
{
    const int BUFFER_SIZE = 1024;
    static PersistentStorage ps;

    const byte hostPort = 80;

    public static void Main()
    {
        ps = new PersistentStorage("SD");
        ps.MountFileSystem();

        byte[] ip = { 192, 168, 0, 200 };
        byte[] subnet = { 255, 255, 255, 0 };
        byte[] gateway = { 192, 168, 0, 1 };
        byte[] mac = { 43, 185, 44, 2, 206, 120 };
        WIZnet_W5100.Enable(SPI.SPI_module.SPI1, (Cpu.Pin)FEZ_Pin.Digital.Di10, (Cpu.Pin)FEZ_Pin.Digital.Di9, true); // WIZnet interface on FEZ Connect
        
        NetworkInterface.EnableStaticIP(ip, subnet, gateway, mac);
        NetworkInterface.EnableStaticDns(new byte[] { 192, 168,0, 1 });
        //Dhcp.EnableDhcp(mac);
        Debug.Print("Network settings:");
        Debug.Print("IP Address: " + new IPAddress(NetworkInterface.IPAddress).ToString());
        Debug.Print("Subnet Mask: " + new IPAddress(NetworkInterface.SubnetMask).ToString());
        Debug.Print("Default Getway: " + new IPAddress(NetworkInterface.GatewayAddress).ToString());
        Debug.Print("DNS Server: " + new IPAddress(NetworkInterface.DnsServer).ToString());
        // Starts http server in another thread.
        Thread httpThread = new Thread((new PrefixKeeper("http")).RunServerDelegate);
        httpThread.Start();
       
        try
        {
            RunServer("http");
        }
        catch (Exception e)
        {
            Debug.Print(e.Message);
        }
    }

    /// <summary>
    /// All this class does is keeps the prefix and provides 
    /// RunServerDelegate to run in separate thread.
    /// RunServerDelegate calls HttpServerApp.RunServer with saved prefix.
    /// </summary>
    class PrefixKeeper
    {
        /// <summary>
        /// Keeps the prefix to start server.
        /// </summary>
        private string m_prefix;

        /// <summary>
        /// Saves the prefix
        /// </summary>
        /// <param name="prefix">Prefix</param>
        internal PrefixKeeper(string prefix)
        {
            m_prefix = prefix;
        }
        
        /// <summary>
        /// Delegate to run server in separate thread.
        /// </summary>
        internal void RunServerDelegate()
        {
            MyHttpServer.RunServer(m_prefix);
        }
    }

    internal static void RunServer(string prefix)
    {
        HttpListener listener = new HttpListener(prefix, -1);
                   
       [b]listener.Start();

[/b]
while (true)
{
HttpListenerResponse response = null;
HttpListenerContext context = null;

            try
            {
                context = listener.GetContext();
                response = context.Response;
                HttpListenerRequest request = context.Request;
                switch (request.HttpMethod.ToUpper())
                {
                    case "GET":  ProcessClientGetRequest(context);  break;
                    case "POST": ProcessClientPostRequest(context); break;
                }

                if (response != null)
                {
                    response.Close();
                }
                if (context != null)
                {
                    context.Close();
                    context = null;
                }
            }
            catch 
            {
                if (context != null)
                {
                    context.Close();
                    context = null;
                }
                if (response != null)
                {
                    response.Close();
                }
            }
        }
    }

    private static void ProcessClientPostRequest(HttpListenerContext context)
    {
        // Retrieves request and response.
        HttpListenerRequest request = context.Request;
        HttpListenerResponse response = context.Response;
        
        // Allocates buffer for reading of message body
        byte[] postdata = new byte[BUFFER_SIZE];

        // Now reads the posted data. The content length should be supplied. 
        // It is error not to have content length with post request.
        if (request.ContentLength64 > 0)
        {
            Debug.Print("Request Headers:");
            Debug.Print(request.Headers.ToString());

            VolumeInfo []vis = VolumeInfo.GetVolumes();
            bool fHasVolume = false;

            if (vis.Length > 0)
            {
                for (int i = 0; i < vis.Length; i++)
                {
                    if (vis[i].Name.ToLower() == "sd")
                    {
                        if (!vis[i].IsFormatted)
                        {
                            vis[i].Format(0);
                        }
                        fHasVolume = true;
                        break;
                    }
                    
                }
            }

            FileStream fs = null;

            if (fHasVolume)
            {
                try
                {
                    fs = new FileStream("\\SD\\Upload.txt", FileMode.Create);
                }
                catch
                {
                     fHasVolume = false;
                }
            }

            long totalBytesReceived = 0;
            long contLen = request.ContentLength64;
            while (totalBytesReceived < contLen)
            {
                int bytesToRead = (int)(contLen - totalBytesReceived);
                // Limit to buffer size
                bytesToRead = bytesToRead < BUFFER_SIZE ? bytesToRead : BUFFER_SIZE;

                int dataRead = request.InputStream.Read(postdata, 0, bytesToRead);
                if (dataRead == 0)
                {
                    // Definitely some error. Means file incomplete.
                    break;
                }

                if (fHasVolume)
                {
                    fs.Write(postdata, 0, dataRead);
                }

                totalBytesReceived += dataRead;
            };

            if (fHasVolume)
            {
                fs.Close();
            }

            // Sends response:
            string strResp = "<HTML><BODY>.Net Micro Framework Example HTTP Server<p>";
            
            // Print requested verb, URL and version.. Adds information from the request.
            strResp += "HTTP Method: " + request.HttpMethod + "<br> Requested URL: \"" + request.RawUrl +
                "<br> HTTP Version: " + request.ProtocolVersion + "\"<p>";

            strResp += "Amount of data received in message body: " + totalBytesReceived + "<br>";    
            strResp  += "Data of message body is discarded (if there is no filesystem). Please review HTTP Server sample code to add processing of data";    
            strResp  += "</BODY></HTML>";
            response.StatusCode = (int) HttpStatusCode.OK;
            //response.RedirectLocation = "http://localhost/WINFS/DpwsDevice/";
            byte[] messageBody = Encoding.UTF8.GetBytes(strResp);
            response.ContentType = "text/html";
            response.OutputStream.Write(messageBody, 0, messageBody.Length);

        }
        else // Content length is missing, send error back
        {
            // Sends response:
            string strResp = "<HTML><BODY>Content length is missing in Post request</BODY></HTML>";
            byte[] messageBody = Encoding.UTF8.GetBytes(strResp);
            response.ContentType = "text/html";
            response.OutputStream.Write(messageBody, 0, messageBody.Length);
        }
    }

    static private string GetPathFromURL(string URL)
    {
        char[] szFilePath = URL.ToCharArray();
        
        for( int i = 0, length = szFilePath.Length; i <  length; i++ )
        {
            if (szFilePath[i] == '/')
            {
                szFilePath[i] = '\\'; 
            }
        }
        // Return updated string with \SD in front
        return new string( szFilePath );
    }

    private static Encoding encoder = Encoding.UTF8;
    private static char[] fwdSlashDelim = { '\\' };

    private static void ProcessClientGetRequest( HttpListenerContext context )
    {
        Debug.Print(Debug.GC(true).ToString());
        HttpListenerRequest request = context.Request;
        HttpListenerResponse response = context.Response;
        
        string strFilePath = GetPathFromURL(request.RawUrl);
        // There is one particular URL that we process differently
        if (strFilePath == "\\PasswordProtected")
        {
            ProcessPasswordProtectedArea(request, response);
            return;
        }
        
        response.StatusCode = (int)HttpStatusCode.OK;
        // Find if file is present. If file exists - sends its context
        if (File.Exists(strFilePath))
        {
            SendFileOverHTTP(response, strFilePath);
        }
        else // The path is directory or not present.
        {
            // Start HTML document
            string strResp = "<HTML><BODY>.Net Micro Framework Example HTTP Server<p>";

            // Print requested verb, URL and version.. Adds information from the request.
            strResp += "HTTP Method: " + request.HttpMethod + "<br> Requested URL: \"" + request.RawUrl +
                "<br> HTTP Version: " + request.ProtocolVersion + "\"<p>";

            // Information about the path that we access.
            strResp += "File to access " + strFilePath + "<p>";

            // If directory present - iterate over it and 
            if (Directory.Exists(strFilePath))
            {
                strResp += FillDirectoryContext(strFilePath, request);
            }
            else // Neither File or directory exists
            {
                // Prints that directory is not found.
                strResp += "Directory: \"" + strFilePath + "\" Does not exists";
            }

            // Closes HTML
            strResp += "</BODY></HTML>";

            // Sends it.
            byte[] messageBody = encoder.GetBytes(strResp);
            response.ContentType = "text/html";
            response.OutputStream.Write(messageBody, 0, messageBody.Length);
        }
        Debug.Print(Debug.GC(true).ToString());
    }

    private static void ProcessPasswordProtectedArea(HttpListenerRequest request, HttpListenerResponse response)
    {
        string strResp = "<HTML><BODY>.Net MF Example HTTP Server. Secure Area<p>";
        if (request.Credentials != null)
        { // Parse and Decode string.
            Debug.Print("User Name : " + request.Credentials.UserName);
            Debug.Print("Password : " + request.Credentials.Password);
            if (request.Credentials.UserName != "Igor" || request.Credentials.Password != "MyPassword")
            {
                strResp += "Authentication failed. <br>You supplied <p>User Name: " + request.Credentials.UserName +
                           "<br>Password: " + request.Credentials.Password;
                strResp += "<p>Please look at root page for required credentials";
                response.StatusCode = (int)HttpStatusCode.Unauthorized;
                response.Headers.Add("WWW-Authenticate: Basic realm=\".Net MF Example of Secure Area\"");
            }
            else
            {
                response.StatusCode = (int)HttpStatusCode.OK;
                strResp += "Authentication Succeeded.";
            }
        }
        else
        {
            strResp += "<p> Authentication Required<p> Please look at root page for required credentials";

            response.StatusCode = (int)HttpStatusCode.Unauthorized;
            response.Headers.Add("WWW-Authenticate: Basic realm=\".Net MF Example of Secure Area\"");
        }

        // Closes HTML
        strResp += "</BODY></HTML>";
        byte[] messageBody = encoder.GetBytes(strResp);
        response.ContentType = "text/html";
        response.OutputStream.Write(messageBody, 0, messageBody.Length);
    }

    static string FillDirectoryContext(string strFilePath, HttpListenerRequest request )
    {
        string strRet = "Context of directory: \"" + strFilePath + "\"<p>";

        try
        {
            string[] dirs = Directory.GetDirectories(strFilePath);
            foreach (string strDirPath in dirs)
            {
                // dirs keep full path. We need only relative path in directory.
                // So we need to split by '\' and take the last directory,
                string[] splitDir = strDirPath.Split(fwdSlashDelim);
                string strDir = splitDir[splitDir.Length - 1];
                string strUrl = request.RawUrl;
                if (strUrl[strUrl.Length - 1] != '/')
                {
                    strUrl += '/';
                }
                strRet += "Dir  - " +
                "<A HREF=\"" + strUrl + strDir + "\">" + strDir + "</A><br>";
            }

            string[] files = Directory.GetFiles(strFilePath);
            foreach (string locFilePath in files)
            {
                string[] splitFile = locFilePath.Split(fwdSlashDelim);
                string strFile = splitFile[splitFile.Length - 1];
                string strUrl = request.RawUrl;
                if (strUrl[strUrl.Length - 1] != '/')
                {
                    strUrl += '/';
                }

                strRet += "File - " +
                "<A HREF=\"" + strUrl + strFile + "\">" + strFile + "</A><br>";
            }
        }
        catch
        {
        }
        
        // Following line adds file post capabilities
        strRet += "<p>Below is example of sending file data to HTTP server";
        strRet += HttpServerSample.Resource1.GetString(HttpServerSample.Resource1.StringResources.PostForm);
        // Next line shows link protected by password.
        strRet += "<br>Below is example of protected link.";
        strRet += "<br><A HREF=\"/PasswordProtected\">Password Protected Secure Area</A>";
        strRet += "<br>Use following credentials to access it:<br> User Name: Igor<br> Password: MyPassword<br>";

        return strRet;
    }
    
    static void SendFileOverHTTP(HttpListenerResponse response, string strFilePath )
    {
        if (strFilePath.IndexOf(".cs") != -1 ||
             strFilePath.IndexOf(".txt") != -1 ||
             strFilePath.IndexOf(".csproj") != -1
           )
        {
            response.ContentType = "text/plain";
        }

        if (strFilePath.IndexOf(".jpg") != -1 ||
            strFilePath.IndexOf(".bmp") != -1 ||
            strFilePath.IndexOf(".jpeg") != -1
          )
        {
            response.ContentType = "image";
        }

        if (strFilePath.IndexOf(".htm") != -1 ||
            strFilePath.IndexOf(".html") != -1
          )
        {
            response.ContentType = "text/html";
        }

        if (strFilePath.IndexOf(".mp3") != -1 ||
            strFilePath.IndexOf(".MP3") != -1)
        {
            response.ContentType = "audio/mpeg";
        }
        Debug.EnableGCMessages(false);
        FileStream fileToServe = null;
        try
        {
            byte[] buf = new byte[4096];
            fileToServe = new FileStream(strFilePath, FileMode.Open, FileAccess.Read);
            long fileLength = fileToServe.Length;
            // Once we know the file length, set the content length.
            response.ContentLength64 = fileLength;
            // Send HTTP headers. Content lenght is ser
            Debug.Print("File length " + fileLength);
            // Now loops sending all the data.

            
            for (long bytesSent = 0; bytesSent < fileLength; )
            {
                // Determines amount of data left.
                long bytesToRead = fileLength - bytesSent;
                bytesToRead = bytesToRead < 4096 ? bytesToRead : 4096;
                // Reads the data.
                fileToServe.Read(buf, 0, (int)bytesToRead);
                // Writes data to browser
                response.OutputStream.Write(buf, 0, (int)bytesToRead);
               
                System.Threading.Thread.Sleep(10);
                // Updates bytes read.
                bytesSent += bytesToRead;
               // Debug.GC(true);
            }
            
            fileToServe.Close();
            //GC.WaitForPendingFinalizers();
            Debug.Print( Debug.GC(true).ToString());
            
        }
        catch (Exception e)
        {
            if (fileToServe != null)
            {
                fileToServe.Close();
            }
            throw e;
        }
        
   }
}

}


#6

Please “code tag” the code so it is readable.

Can you please give us a list of what assemblies (DLLs) are included in your project?


#7

You are using this, right?
http://wiki.tinyclr.com/index.php?title=WIZnet_W5100_HTTP_FileServer

I suggest that you use the project as is. You Probably will need to remove FEZ Panda II assembly and replace it with FEZ Domino’s


#8

I think I found the cause.

I do not have the GHIElectronics.NETMF.W5100.Http.dll as in the original project, instead I have the System.http; the reason is I do not find the GHIElectronics.NETMF.W5100.Http.dll in my computer.

Do you know where can I find it ?

thanks for the support


#9

if you do not have the W5100 bits then you don’t have an up-to-date GHI SDK. You need to install a more recent one, as W5100 support was only added in one of the last few releases.


#10

Yes, I think this should be the problem.
I uninstalled the microsoft framework and the GHI sdk; I reinstalled again everything (1st the framework and after the sdk) and the dlls are now in the PC; but I got the following errors ; I checked the dll versions and they are ok … too bad to be true…

Assembly: GHIElectronics.NETMF.W5100.Http (4.1.5.0) needs assembly ‘GHIElectronics.NETMF.W5100’ (4.1.5.0)
Assembly: GHIElectronics.NETMF.IO (4.1.5.0) needs assembly ‘GHIElectronics.NETMF.System’ (4.1.5.0)
Assembly: FEZ Domino Application (1.0.0.0) needs assembly ‘GHIElectronics.NETMF.IO’ (4.1.5.0)
Assembly: FEZ Domino Application (1.0.0.0) needs assembly ‘GHIElectronics.NETMF.W5100.Http’ (4.1.5.0)
Assembly: FEZ Domino Application (1.0.0.0) needs assembly ‘GHIElectronics.NETMF.W5100’ (4.1.5.0)
Assembly: GHIElectronics.NETMF.Net (4.1.5.0) needs assembly ‘Microsoft.SPOT.Hardware.SerialPort’ (4.1.2821.0)
Assembly: GHIElectronics.NETMF.Net (4.1.5.0) needs assembly ‘GHIElectronics.NETMF.System’ (4.1.5.0)


#11

Remove these references from your vs solution and re-add them.


#12

Hello,

No result …
In the line " Assembly: GHIElectronics.NETMF.Net (4.1.5.0) needs assembly ‘Microsoft.SPOT.Hardware’ (4.1.2821.0)" I checked both versions and they are matching, so I do not know what is going on

thanks


#13

I did an upgrade to the firmware and it seems ok
Thanks for all your support


#14

To avoid frustration, All you you need in this page, specially the tutorials: :wink:
http://tinyclr.com/support


#15

thanks once more


#16

Thank you for using FEZ. 8)

We are looking forward to seeing your creative projects.