Gadgeteer Web Server and "Streaming of embedded resources"

Hi,

i sat that ResourceUtility.GetObject has an override with offset and lenght.

This would be nice to be used with a “streaming” approach… since loading of big resources lead to out of memory exception!

I tryed this code… but didn’t work…

        /// <summary>
        /// Updates the data with which the web event responds and sets the correct MIME type.
        /// </summary>
        /// <param name="resourceManager"></param>
        /// <param name="resourceId"></param>
        /// <param name="ContentType"></param>
        public void Respond(System.Resources.ResourceManager resourceManager, Enum resourceId, string ContentType)
        {
            webEvent.ContentType = ContentType;

            BinaryResponseTemplate template = this.webEvent.ComputeResponse();
            
            if (template.Header != null && template.Header.Length > 0)
            {
                //send the http header
                this.ClientSocket.Send(template.Header, 0, template.Header.Length, SocketFlags.None);

                bool resourceEnded = false;
                int offset = 0;

                while(!resourceEnded)
                {
                    try 
	                {
                        byte[] resourceBlock = (byte[])ResourceUtility.GetObject(resourceManager, resourceId,
                            offset, 32);

                        var sent = this.ClientSocket.Send(resourceBlock, 0, resourceBlock.Length, SocketFlags.None);
	                }
	                catch (Exception)
	                {
		                resourceEnded = false;
	                }

                    offset += 32;
                }

                this.ClientSocket.Close();
            }       
        }

Any comments???

@ andre.marschalek - in that case i got out of memory!! My resource is 56k!! top big for a stack buffer…

mountaineer ethernet…

i will try… i m just wondering if there will ne enought room in RAM to lo ad a big embedded resource

@ AlbeNET -

I also made some tests with this board for IP communication, HTTP and so on, but the limited memory provided by the M4 made me left it for the G120.

In my case, I had to play with html pages in resources, and some parsable fields contained in those pages. I had to really work around my parsing method to ensure to fit the memory instead of what it rapidly throw OutOfMemory.

Finally, considering that I would like also to add some other things than HTTP server, I recognized that I will have to choose between finding a way to increase the available memory, or to swtich to something more memory performant : this is why I choose the G120…

Cortex-M4 provided in MOuntaineer is enough to play with I/O and a well sized packet communication on Serial or pure IP for example, but not much more !

So, verify your needs for cumulated functions and memory needs before continuing on this board.

But one thing is sure : you can use it to test your methods and verify their memory needs ! If they work on the M4, they will on the G120 :slight_smile:

Hood to know… so finally… just a small pure HTML page

Agree with Andre !

piece by piece is the only way ! To minimize coupling between the way you read the buffer, and the htttp stream output, you can use delegate events for example…

an event is thrown by the reading method, within param the read buffer. When received by the Http class, it ouput it,
another event is thrown to tell reading ended. When received by the Http class, it finalize the stream…

Guys, all.

i know that the best is the option 2. i’m not a newbe of software design / architecture…

now i’m talking about code, and code with .NET Microframework 4.2 QFE2

          while(!resourceEnded)
                {
                    try 
	                {
                        byte[] resourceBlock = (byte[])ResourceUtility.GetObject(resourceManager, resourceId,
                            offset, 32);

                        var sent = this.ClientSocket.Send(resourceBlock, 0, resourceBlock.Length, SocketFlags.None);
	                }
	                catch (Exception)
	                {
		                resourceEnded = false;
	                }

                    offset += 32;
                }

Look at the code… the idea was exactly that!!!..

There is two problems:

  1. Undestand when the resouce is finished. I know that there is a small bug in the “GetObject” method.

  2. ClientSoket.Send hang when called twice on a Mountaineer Ethernet board.

Any suggestion on this specific two topics?

Thanks
Al

We apologize, but it is neither written on the tip of your avatar nose, neither on your uncompleted profile…

However, it could be interesting to have a piece of project that I could test on my Mountaineer Ethernet, and tell you back if I have the same problems…

@ LouisCpro - Sorry you are right… profile updated…

Here is the web server class lib from gadgeteer modified…

I’ve added this response method… in the Responder.cs class

public void Respond(System.Resources.ResourceManager resourceManager, Enum resourceId, string ContentType)

and i’ve applied one patch regarding the “Default” event. from gadgeteer codeplex site.

Basically i’m not able to respond a content form an embedded resource…

i got a socket exception without any details!!!

change the extension to zip

Forgot the attachment ?

@ LouisCpro - sorry i don’t know whats upp… it didn’t get

@ AlbeNET -

I guess you can not upload something else than images. Yu can also send the zip to louis@ … (domain in my profile)

@ LouisCpro - the domain is proXXXXs.com ?

Yes

ok sent…

@ AlbeNET -

OK, Compile and Run… Now what, do you need to send me your big Html page ?

I’ve changed the method in this way:

 /// <summary>
        /// Updates the data with which the web event responds and sets the correct MIME type.
        /// </summary>
        /// <param name="resourceManager"></param>
        /// <param name="resourceId"></param>
        /// <param name="ContentType"></param>
        public void Respond(System.Resources.ResourceManager resourceManager, Enum resourceId, string ContentType)
        {
            Debug.Print("FREE RAM: " + Debug.GC(true));

            webEvent.ContentType = ContentType;
            int contentLenght = 0;
            
            int blockSize = 512;

            bool resourceEnded = false;
            int offset = 0;
            
            //before all...  compute resource lenght! this is "stupid"... but this is the only way to know the dimension of a resource!
            while (!resourceEnded)
            {
                byte[] resourceBlock = (byte[])ResourceUtility.GetObject(
                                               resourceManager, resourceId,
                                               offset, blockSize);

                if (resourceBlock.Length < blockSize)
                {
                    resourceEnded = true;
                }

                offset += blockSize;
                contentLenght += blockSize;
            }

            BinaryResponseTemplate template = new BinaryResponseTemplate(webEvent.ContentType, contentLenght);
            
            if (template.Header != null && template.Header.Length > 0)
            {
                //send the http header
                this.ClientSocket.Send(template.Header, 0, template.Header.Length, SocketFlags.None);

                resourceEnded = false;
                offset = 0;

                Debug.Print("FREE RAM: " + Debug.GC(true));

                while(!resourceEnded)
                {
                    try 
	                {                       
                        byte[] resourceBlock = (byte[])ResourceUtility.GetObject(
                                                                    resourceManager, resourceId,
                                                                    offset, blockSize);

                        if (resourceBlock.Length < blockSize)
                        {
                            resourceEnded = true;
                        }

                        var sent = this.ClientSocket.Send(resourceBlock); //, 0, resourceBlock.Length, SocketFlags.None);

                        //System.Threading.Thread.Sleep(10);
	                }
	                catch (Exception ex)
	                {
                        Debug.Print(ex.ToString());
		                resourceEnded = true;
	                }

                    offset += blockSize;
                }

                this.ClientSocket.Close();
            }       
        }

Now seems working!!! BUT… . basically what i stream was a big XAP file that contains a silverlight application… 54kB of XAP…

the problem was that i need to set the content lenght in HTTP… it didn’t work yet 100% (i cannot see the xap loeded in my browser)… but at least i didn’t get exceptions!