Using WebSockets

WebSockets are bidirectional, full-duplex channels that start as HTTP channels and use handshakes to upgrade the channels to WebSockets, with real, two-way TCP communication between the client and the server. The added benefit is that all of this can happen through port 80 and that they are router friendly.

In this recipe, we will see how to create and consume a WebSockets service.

Getting ready

In order to use this recipe, you should have Windows 8 with Visual Studio 2012 installed. WebSockets are only supported natively on Windows 8; see http://msdn.microsoft.com/en-us/library/hh159285.aspx.

How to do it...

Here, we are going to set up our system in order to support WebSockets and implement a basic WebSocket.

  1. First, we need to validate that the following Windows features are installed on our Windows 8 machine:
    • ASP.NET 4.5 and HTTP activation
    • WebSockets over Internet Information Services
    How to do it...
  2. Open Visual Studio 2012; create a new project by navigating to Visual C# | Web and use the ASP.NET Empty Web Application template to create a web project to host the web service. Name it WebSocketsWcf and click on the OK button.
  3. Right-click on the project and add a new item of the type WCF Service; then name it WebSocketsService.svc and click on the Add button.
  4. Open the generated IWebSocketsService.cs file and replace the code with the following:
    [ServiceContract(CallbackContract = typeof(IWebSocketsServiceCallback))]
    public interface IWebSocketsService
    {
        [OperationContract(IsOneWay = true)]
        Task StartSendingData();
    }
  5. Note that we will have to add a reference to System.Threading.Tasks to add support for asynchronous operations and types.
  6. We will get an indication for the IWebSocketsServiceCallback exception, which we will solve on the next step.
  7. Create a IWebSocketsServiceCallback.cs class and add the following code:
     [ServiceContract]
    public interface IWebSocketsServiceCallback
    {
        [OperationContract(IsOneWay = true)]
        Task SendData(string data);
    }
  8. Note that we have to add a usings clause for System.Threading.Tasks and for the System.ServiceModel namespaces.
  9. Open the WebSocketsService.svc.cs file and substitute the following for the code:
    public class WebSocketsService : IWebSocketsService
    {
    public async Task StartSendingData()
        {
    Var callbackFunction = OperationContext.Current.GetCallbackChannel<IWebSocketsServiceCallback>();
    
    while ((callbackFunction as IChannel).State == CommunicationState.Opened)
            {
    await callbackFunction.SendData("Hi, the time is : " + DateTime.Now.ToLongTimeString());
    await Task.Delay(5000);
            }
        }
    }
  10. At this point, we need to add a reference to System.Threading.Tasks and System.ServiceModel.Channnels.
  11. Edit the Web.Config file and substitute the following for the code:
    <?xml version="1.0"?>
    <configuration>
    <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
    </appSettings>
    <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntimetargetFramework="4.5" />
    </system.web>
    
    <system.serviceModel>
    <protocolMapping>
    <add scheme="http" binding="netHttpBinding" />
    <add scheme="https" binding="netHttpsBinding" />
    </protocolMapping>
    <behaviors>
    <serviceBehaviors>
    <behavior name="">
    <serviceMetadatahttpGetEnabled="true" httpsGetEnabled="true" />
    <serviceDebugincludeExceptionDetailInFaults="false" />
    </behavior>
    </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironmentaspNetCompatibilityEnabled="true"
    multipleSiteBindingsEnabled="true" />
    </system.serviceModel>
    </configuration>
  12. Build the application.
  13. Add a new project by navigating to Visual C# | Windows and selecting the Console Application template. Name it WebSocketsConsoleClient and press the OK button.
  14. Set it as the startup project.
  15. Right-click on the newly added project and select Add Service Reference.
  16. Click on the Discover button and the recently defined WebSockets service should appear. Select it, and in the Namespace parameter type WebSocketsServiceReference and press the OK button.
  17. Add a new class named WebSocketsCallbackHandler to the console project with the following code:
    class WebSocketsCallBackHandler : WebSocketsServiceReference.IWebSocketsServiceCallback
    {
        public void SendData(string data)
        {
            Console.WriteLine("Received data from the WebSockets service: " + data);
        }
    }
  18. Continue by opening the Program.cs file and substituting the main method with the following code:
    static void Main(string[] args)
    {
        try
        {
            Var InstanceCtx = new InstanceContext(new WebSocketsCallBackHandler());
            Var WebSocketsClient = new WebSocketsServiceReference.WebSocketsServiceClient(InstanceCtx);
    
            WebSocketsClient.StartSendingData();
    
            Console.ReadLine();
    
        }
        catch (Exception ex)
        {
    
        throw;
        }
    }
  19. We have to add a using clause for the System.ServiceModel namespace.
  20. Open the App.config file that was autogenerated when we added the service reference, and validate that the endpoint definition has its binding set to netHttpBinding.
  21. Now let's build and execute our solution; if all goes well, we should see the following result on our console:
    How to do it...
  22. And that's it; we just created a WebSockets WCF service and a client that consumes it!

How it works...

First, we configured our Windows 8 operating system to support WebSockets, ASP.NET 4.5, and HTTP activation features. It is necessary to have .NET 4.5 on the operating system, either by installing it automatically when performing the installation of Visual Studio 2012 or by installing it as a standalone.

Note that WebSockets will not run on previous operating systems that don't have IIS8 installed, so this feature is unsupported natively on Windows 7.

We created an ASP.NET web app to host our web service and added the following attribute to it:

[ServiceContract(CallbackContract = typeof(IWebSocketsServiceCallback))]

Essentially, we are defining ServiceContract and setting up IWebSocketsServiceCallback as the callback context.

Then on the interface, we added just one method, StartSendingData(), with the attribute:

[OperationContract(IsOneWay = true)]

This indicates that this method will only move in one direction, that is, from the client to the server. We are going to use it as a handshake that will set up the communication between the client and the server.

Note that we are using tasks, so this will comply with the async/await model that .NET 4.5 can be proud of.

Next we have created IWebSocketsServiceCallback, which is also a service contract, where we defined the SendData() method task that we set to follow a one-way route. We will obviously use this to send data which the clients usually updates. Note that we need to implement this on the client too, for this to work properly.

To continue, we need to implement the interfaces we just defined. For WebSocketsService, we set up the StartSendingData() method that gets the current callback channel. While the channel is open, we keep on executing asynchronous calls to the callback method.

In order to finish the server part, we use configuredWeb.Config where we have added a protocol mapping for HTTP and HTTPS to netHttpBinding/netHttpBindings, which we will use for our WCF endpoints.

We built the project and added a console application that will be the client of our service. In the console application, we had to add a service reference to our recently created web service.

We created a class called WebSocketsCallBackHandler to hold our implementation of the callback method. The received data is redirected to the console with a WriteLine command.

In our main method, we'll create an instance of this class with the callback handler class as its parameter, thus generating a client for our web service. From the following instance, we just call the handshake method that will trigger the server to start sending data.

Var InstanceCtx = new InstanceContext(new WebSocketsCallBackHandler());
Var WebSocketsClient = new WebSocketsServiceReference.WebSocketsServiceClient(InstanceCtx);
WebSocketsClient.StartSendingData();

And that's all there is to it! Notice how, despite its power, the solution is extremely simple.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset