Understanding Server-Sent Events
Tags: serversentevents, netcore, net, aspnetcore
Published: 2020-01-23 10:58:27

---
title: Understanding Server-Sent Events
published: true
description: Understanding the server-sent events and a quick sample with .net core
tags: #server-sent-events #net-core #.net #aspnetcore
---
Since a last few weeks I have been checking this with a lot of dev(s) that I know, if they are aware of server-sent events. Surprisingly a very few of them know what is a server-sent event. Let us understand this term.

#What is SSE?
As the name suggests, an event that is sent or initiated by a server, and this is exactly what it does.
According to the [wiki page]("https://en.wikipedia.org/wiki/Server-sent_events"), *Server-Sent Events (SSE) is a server push technology enabling a client to receive automatic updates from a server via HTTP connection*.
This is standardized as the part of HTML5. The server-sent event is an API that is operated through the [EventSource]("https://developer.mozilla.org/en-US/docs/Web/API/EventSource") interface

A client subscribes to a “stream” from a server and the server will send messages (“event-stream”) to the client until the server closes the stream. 
It is the server that decides when and what to send the client and when to end the stream.

#Why should you know about SSE?
Since the applications and their users are becoming more real-time oriented, you need Server-Sent Events. Displaying the last data updates to your users may change their actions.

#Why SSE? I have Websockets.
[WebSockets]("https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API") indeed is a long awaited evolution in client/server web technology. They allow a 
single TCP socket connection to be established between the client and server which allows for bi-directional, full duplex, messages to be instantly distributed. Now there is a catch, if you read this meticulously, you would definitely notice that WebSockets are bi-directional. So if I need only unidirectional, WebSockets will cause great latency issues.

SSE is single directional (server to client) which surely would improve the latency issues. If we are looking from a server load point of view, SSE can be a way much better option than WebSockets.

#Fields
As per the MDN, an event stream is a simple stream of text data which must be encoded using UTF-8. Messages in the event stream are separated by a pair of newline characters. A colon as the first character of a line is in essence a comment, and is ignored.

Each message received has some combination of the following fields, one per line:

###event
A string identifying the type of event described. If this is specified, an event will be dispatched on the browser to the listener for the specified event name; the website source code should use addEventListener() to listen for named events. The onmessage handler is called if no event name is specified for a message.

###data
The data field for the message. When the EventSource receives multiple consecutive lines that begin with data:, it will concatenate them, inserting a newline character between each one. Trailing newlines are removed.

###id
The event ID to set the EventSource object's last event ID value.

###retry
The reconnection time to use when attempting to send the event. This must be an integer, specifying the reconnection time in milliseconds. If a non-integer value is specified, the field is ignored.

[click here for MDN Docs]("https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events")


#Examples
To use the server-sent events, we need to call an API from a client and then the server will keep on sending the events, till the stream is closed.

###.Net Core 
Create a controller with any route. Add the following code to the controller.
```
        [HttpGet]
        public async Task Get()
        {
            var response = Response;
            response.Headers.Add("Content-Type", "text/event-stream");

            for (var i = 0; true; ++i)
            {
                await response.WriteAsync($"data: Controller {i} at {DateTime.Now}\r\r");

                response.Body.Flush();
                await Task.Delay(5 * 1000);
            }
        }
```

In this implementation we are using the WriteAsync method in from the [Microsoft.AspNetCore.Http]("https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http?view=aspnetcore-3.1") namespace. The writeAsync method will write the given text to the response body with the UTF-8 encoding.

###HTML
```
<html>

<body>
    <script type="text/javascript">
        if (!!window.EventSource) {
            var source = new EventSource('https://localhost:44317/api/sse');
            source.addEventListener('message', function (e) {
                console.log(e.data);
            }, false)

            source.addEventListener('open', function (e) {
                console.log(e);
            }, false)

            source.addEventListener('error', function (e) {
                if (e.eventPhase == EventSource.CLOSED)
                    source.close()
                if (e.target.readyState == EventSource.CLOSED) {
                    console.log("Disconnected");
                }
                else if (e.target.readyState == EventSource.CONNECTING) {
                    console.log("Connecting...");
                }
            }, false)
        } else {
            console.log("Your browser doesn't support SSE")
        }
    </script>
</body>

</html>
```

When I ran the HTML, this is how the output was showing up in the console.
![sse](https://thepracticaldev.s3.amazonaws.com/i/nr5v29mbion8uhwa8p0e.gif)