Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML5

Learn HTML 5 in 3 days – Day 3 – Part 1

4.98/5 (17 votes)
19 Apr 2016CPOL8 min read 30.4K   1.1K  
In this article we will talk about Server Sent Events in detail.

Introduction

So finally you have reached final day, Day 3. I believe last two days have been fun for you all. It’s the final stage of all – Day 3. Day 3 is written a little differently. In Day 3 we will talk about Server Sent Events in detail. HTML5

 

Complete List

Why Server sent events?

Server-sent events (SSE) is a technology where a browser receives automatic updates from a server via HTTP connection.

Let’s make this definition easy with the help of a scenario. Let say we have a HTML page. Requirement is simple. That HTML page will continuously get the updated data from server and display it in the UI.

Old Approach

The traditional way of accomplishing this requirement is “polling”. In polling we will send an Ajax requests to server and get the response. Once the response is received HTTP connection responsible for this communication get closed. After some time it will be repeated once again using a new HTTP connection and keep on repeating. It is a concept of polling.

1 – Get HTML page

Image 2

2 – From HTML page make request to server for data

Image 3

Concept of streaming response

Continues polling affect the overall performance. The one solution is steaming response by server. Once the request is made, server will return the response but as a stream of data.

Streaming

I am sure you have seen YouTube. It’s the best example of streaming. Instead of returning whole video at once, only a small chunk of video is returned from the server and the YouTube player start playing that small chunk. But server won’t stop there, it keep on sending more chunks regularly. This concept is called as Streaming. More precisely in case of videos it is called as streaming media.

In the same way other data can be streamed as well. In Simple words, Client will ask server for some data, server return some data and instead of ending execution and closing connection, server will continuously keep sending data. Once there is nothing to send, server will complete the execution and close the connection.

Note: We will soon create a sample server side code using Asp.Net MVC for demonstrating data streaming.

Streaming is not possible with normal Ajax Call

Traditional Ajax call made using XmlHttpRequest won’t let us get stream of data. Using Ajax, we will send asynchronous request to server (from JavaScript). Once the response is received in JavaScript, connection get simply closed automatically by client side. It won’t wait for next stream to return.

New Approach – Server Sent Events

In case of SSE situation will be a little different. Here we will have two things

  1. Server – Which will continuously send a stream of data.
  2. A HTML page which will make request to server using EventSource object. EventSource is a new HTML5 concept meant for working with SSE.

EventSource object provides a callback function which will get executed every time server send some response.

1 – Get HTML page

Image 4

2 – From Html page make request to server for data

Image 5

Let’s do the demonstration and understand it better.

Lab 21 – SSE demonstration

Step 1 - Create Server code

For our example we will choose Asp.Net MVC as a server side technology.

Note: This article more concentrate at HTML 5 SSE rather Asp.net MVC. If you have prior knowledge on Asp.Net MVC it will be good, or else simply follow below steps to prepare the server side part. Don’t even hesitate to download MVC project from the example attached and to use it straight forward.

Step 1.1 – Create Asp.Net MVC project.

Create a new Asp.Net MVC project called ServerSentDemo using Visual studio. You can download Visual studio from here.

Image 6

In the next dialog box select empty in the templates section and MVC in the references section and click Ok.

Image 7

Step 1.2- Create a Controller

Right click the controller folder and select AddNew>>Controller.

Image 8

Select “MVC 5 Controller - Empty” in next dialog box and click Ok.

Image 9

Set name as SSEController and click Ok.

Image 10

Step 1.3- Create Action method

Create and Action method called Index inside SSEController as follows.

C#
publicvoid Index()
{
int i = 0;
do
    {
        Response.Write("Current Date:"+DateTime.Now+"
");
        Response.Flush();
        System.Threading.Thread.Sleep(2000);
        i++;
    } while (i<5);
}

As you can see action method return type is set to void and with the help of Response. Write and Response. Flush response is explicitly generated and returned.

Step 1.4 - Execute and Test

Press F5 and execute the application.

Note: In order to test server code which returns stream of data chrome is the best option. So execute the application in chrome.

Navigate to Index action of SSEController and check the output.

Image 11

As you can see, server is sending back response in stream. Between every data stream there is a gap of 2 seconds.

Step 2 – Create Client Code

In real time scenario, we won’t expose above URL directly to end user. Instead we will create a user friendly URL and with the help of JavaScript we will send request to above URL using HTML 5 concept SSE.

Step 2.1 – Create HTML client file.

Simply Create a HTML page and name it as “SSEClient.html”.

Put following HTML in the newly created html file.

<!DOCTYPEhtml>
<html>
<head>
<metaname="viewport"content="width=device-width"/>
<title>Index</title>
</head>
<body>
<ulid="messages"></ul>
</body>
</html>

It’s a simple HTML content with a div tag. We will display response sent by server inside this div.

Step 2.2 – Implement EventSource

In the HTML file, in Head section create a script tag and handle onload function of windows as follows.

HTML
<scripttype="text/javascript">
window.onload = function () {
var o = new EventSource("http://localhost:13971/SSE/Index");
};
</script>

As you can see, inside onload function EventSource object is created. This line will make a request to server code wrote before.

Step 2.3 – Handle Response Data

EventSource object exposes a property called “onmessage”. This property expects a function as value which will executed each and every time server send something. Write the following code.

HTML
var o = new EventSource("http://localhost:13971/SSE/Index");
o.onmessage = function (e) {
var x = e.data;
var MyDiv = document.getElementById("messages");
    MyDiv.innerHTML = MyDiv.innerHTML + "<li>" + x+ "</li>";
}

Step 2.4 – Execute and Test

Simply double click the SSEClient.html file and execute it. (Make sure server code is up and running.)

Strangely you will see nothing in the output.

Reason for such expected output is runtime error.

Simply open developer tools in your browser. In chrome press F12.

Image 12

By default, browser won’t allow to make request to server in a different domain than your current page is on. In simple words, our HTML file and our server code are not in same domain. One is “localhost:13971” whereas other one is local (C://MyRND.....). In order to make this possible we have to enable CORS in server.

 

Step 3 – Enable CORS in server

Open the server project created before. Open Web.Config file. Inside configuration section create a child tag called system.webServer as follows.

HTML
......
<system.webServer>
<httpProtocol>
<customHeaders>
<addname="Access-Control-Allow-Origin"value="*"/>
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>

Note: If configuration sectionalready contains system.webServer tag , then don’t create it again. Simply put httpProtocol tag inside it as shown above.

Step 4 – Re-execute client

Now rerun the SSECllient.html file again. This time last error will get solved but don’t expect output because new run time error is waiting. Use the developer tools to find out the cause for the error.

Image 13

In order to work with SSE, we will be required a server which will send stream of data with a content type as “text/event-stream”. By default it is “text/html”

Step 5 – Change Server response Content type

Open server code and change Index action method as follows.

HTML
publicvoid Index()
{
    Response.ContentType = "text/event-stream";
int i = 0;
do
    {
        Response.Write("data:" + DateTime.Now + "\n\n");
        Response.Flush();
        System.Threading.Thread.Sleep(2000);
        i++;
    } while (i<5);
}

As you can see, not only Content-Type is set to “text/event-stream” but the output format is changed too. For SSE response format must be “data:ActualDataInStringType\n\n”. It’s a fixed format. “data” is a keyword and actual response text must be continued with two “\n”.

Step 6 – Re-execute client

Once again run SSEClient.html file.

Image 14

So finally we got the output.

Automatic Reconnection?

You may see a very strange behavior in above output. If you keep client open for long time, you will notice that output won’t ends after 5 output. After 5 outputs, server will end the response hence connection get closed. Immediately after 3 seconds automatically a new request will be sent to server and 5 more output will come in streams. This process will repeats forever.

Reason for such behavior is automatic reconnection ability of Event Source object. SSE works on top of HTTP protocol. EventSource object which is responsible for connecting client to server make sure that connection is available all the time. This is how it works.

  • It makes first request to server.
  • Server start processing the request and keep on sending data without ending the response. At client side EventSource object’s onmessage callback get hit every time a response is received.
  • EventSource objectautomatically try to reconnect to the server 3 seconds after each connection is closed.

Again this retry time will be decided by server. Server can return retry time with the response. In such cases response string must have “retry” keyword in it. Example for such response is shown below.

“retry:5000\ndata:SukeshMarla\n\n”

If connection get closed after receiving above data, reconnection attempt will be made after 5 seconds.

Closing the connection

It is only possible in client side. In the client side we have to invoke the close method of EventSource object. Example:

HTML
var o = new EventSource("http://localhost:13971/SSE/Index2");
.
.
.
o.close()

Specifying Event name

A single server is capable of sending different events to client in different situations. It can be done by including event name in the response string. In this case,on the client side, an event listener can be setup to listen to that particular event. Let’s have a simple example.

Step 1 Create a new action method Index2 as follows.

HTML
publicvoid Index2()
{
    Response.ContentType = "text/event-stream";
int i = 0;
do
    {
if (i == 0)
            Response.Write("event:first\ndata:" + DateTime.Now + "\n\n");
elseif (i == 4)
            Response.Write("event:last\ndata:" + DateTime.Now + "\n\n");
else
            Response.Write("data:" + DateTime.Now + "\n\n");
        Response.Flush();
        System.Threading.Thread.Sleep(2000);
        i++;
    } while (i < 5);
}

Step 2 – Create a new HTML file as follows.

HTML
<!DOCTYPEhtml>
<html>
<head>
<metaname="viewport"content="width=device-width"/>
<title>Index</title>
<scripttype="text/javascript">
    window.onload = function () {
var o = new EventSource("http://localhost:13971/SSE/Index2");
        o.onmessage = function (e) {
var x = e.data;
var MyDiv = document.getElementById("messages");
            MyDiv.innerHTML = MyDiv.innerHTML + "<li>" + x+"</li>";
        }
        o.addEventListener("first", function (e) {
            document.getElementById('FirstMessage').innerHTML = e.data;
        });
        o.addEventListener("last", function (e) {
            document.getElementById('LastMessage').innerHTML = e.data;
        });
    };
</script>
</head>
<body>
<h1id="FirstMessage"></h1>
<ulid="messages"></ul>
<h1id="LastMessage"></h1>
</body>
</html>

Step 3 – Execute and test the application

Execute the server and then execute the client.

Image 15

So that’s it.

Hope all of you enjoyed reading this article. Share your comments and thoughts about article for sure. Stay connected via twitter or Facebook to get regular updates about my posts.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)