HTML5 introduced WebSockets, a TCP full duplex channel between a browser and a server. Modern browsers now largely support WebSockets (see support table) and you can always use one of the numerous polyfills to ensure compatibility with older browsers.
WebSockets have been around for a long time but it took a lot of plumbing to have a .NET server up and running before .NET 4.5. Thanksfully, .NET 4.5 introduced the WebSocket class, making it really easy to create a server. Here’s what you need to do to run a WebSocket server.
On the server
First make sure that your WCF web.config has the following:
<system.web>
<httpRuntime targetFramework="4.5" />
</system.web>
Then creating a socket server is as easy as adding a Generic Handler (.ashx) to your project. The full code for a simple server that tracks who is connected to the server is the following:
Public Class WebSocketHandler
Implements System.Web.IHttpHandler
' List of all connected sockets
Private Shared users As New List(Of WebSocket)
' Function called when a client sends a request (connects) to the socket
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
If context.IsWebSocketRequest Then
context.AcceptWebSocketRequest(AddressOf OnConnection)
Else
context.Response.StatusCode = 400
End If
End Sub
Private Async Function OnConnection(ByVal context As AspNetWebSocketContext) As Task
Dim socket As WebSocket = context.WebSocket
' Store the socket
users.Add(socket)
Try
While socket.State = WebSocketState.Open
' Read message incoming from the client (here 1024 is the max size of the message)
Dim buffer As New ArraySegment(Of Byte)(New Byte(1023) {})
Dim result As WebSocketReceiveResult = Await socket.ReceiveAsync(buffer, CancellationToken.None)
' If the client explictely closed the socket
If result.MessageType = WebSocketMessageType.Close Then
users.Remove(socket)
Await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, String.Empty, CancellationToken.None)
End If
' If the socket is open, read the message sent by the client
If socket.State = WebSocketState.Open Then
Dim userMessage As String = Encoding.UTF8.GetString(buffer.Array, 0, result.Count)
' Do something with userMessage
' ...
' Send a message to all connected users
userMessage = "The server received: " & userMessage & " at " & DateTime.Now.ToLongTimeString & " - There are " & users.Count & " connected users."
buffer = New ArraySegment(Of Byte)(Encoding.UTF8.GetBytes(userMessage))
For Each s In users
Await s.SendAsync(buffer, WebSocketMessageType.Text, True, CancellationToken.None)
Next
End If
End While
Catch ex As Exception
' An exception will be thrown if the channel is closed (for example if the client closes the browser)
users.Remove(socket)
End Try
End Function
Public ReadOnly Property IsReusable As Boolean Implements IHttpHandler.IsReusable
Get
Return True
End Get
End Property
End Class
The OnConnection function, called when a client connects to the server, loops indefinitely while the socket is open and waits for messages. When a message is received, it can process it and do whatever is needed. In our example, the server simply sends the message back to all connected users and also tell them how many users are connected.
On the client
Writing the client side is even easier.
Have the browser open the socket:
var socket = new WebSocket("wss://myserver.com/WebSocketHandler.ashx", ['soap']);
Notice the protocol is wss, can be ws for non-secured connections.
Then make sure you know when the socket is open and simply send messages:
socket.onopen = function () {
socket.send("hello");
}
Finally, do something when the client receives a message from the server:
socket.onmessage = function (e) {
alert(e.data);
}
And this is it! You established a WebSocket connection between a browser and your .NET WCF web service and you did not even use any 3rd-party library. Yay!