PowerWebSockets

WebSocket server push example

READY-TO-RUN PROJECTS WITH SAMPLE CODE

For our first PowerWebSockets sample, we will write a PWS client that opens 1,000 connections to a PWS service and bombards it by sending a "Hello world!" message through each of the 1,000 active connections. Upon receiving each of these 1,000 messages, the service will push it to each of the 1,000 active connections. So the service will send back to the client 1,000 messages over each of the 1,000 connections = 1 million “Hello world!” messages.

Let’s start by creating the PWS service.


			
01
02
03
04
05
06
07
08
09
10
11
12
13
using System;
using Noemax.WebSockets;
. . .
public class ServerService : WebSocketService
{  
   public override void OnMessage(WebSocketChannel channel,
                                  WebSocketInboundMessage message)
   {
      // read any type of received message as an outbound message and
      // broadcast it irrespective of the message type
      Broadcast(message); 
   }
}

When the service receives an inbound message it calls the OnMessage method. When overridden, this method provides dispatching and processing of inbound messages. We override the OnMessage method in order to push the message to all channels that are currently connected to the service.

Broadcast(message) pushes the message to all channels that are currently connected to the service. In this sample, calling Broadcast(message) will push each received message back to the 1,000 client connections that we are going to establish with the service endpoint.

In order to accept the client connections we need to provide our service with a server endpoint.


			
01
02
03
04
05
06
07
08
09
10
11
12
13
public static void Main (string[] args)
{
   Console.WriteLine ("Starting the server..");
             
   var server = new WebSocketServer<ServerService>();
   server.AddEndpoint(new Uri("ws://localhost:9090"));
   server.Open();
             
   Console.WriteLine("Server started. Press any key to exit...");
   Console.Read();
             
   server.Close();
}

The WebSocketServer<ServerService> instance can listen on a single or on multiple endpoints. When it is ready to accept client connections, it automatically instantiates an instance of the service.

The server side is ready. Now let’s create the service that will be handling communication on the client side.


			
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using System;
using Noemax.WebSockets;
. . .
class ClientService : WebSocketService
{
   // number of client connections to create
   private const int MaxConnectionNumber = 1000;
   // interval in received messages to print out statistics
   private const int PrintOutInterval = 10000;
   private static Stopwatch stopwatch = new Stopwatch();       
   private static int repliesReceived = 0;
 
   ...
 
   // handles text messages relayed by the server
   public override void OnMessage (WebSocketChannel channel, string text)
   {
      int count = Interlocked.Increment(ref repliesReceived);
      // report statistics
      if (count %  PrintOutInterval == 0)
      {
         Console.WriteLine(count + " messages in " +
               stopwatch.ElapsedMilliseconds + "ms");          
      }
             
      // since the client will broadcast the message through all client
      // channels and since the service will broadcast each received
      // message back to all connected channels, the number of messages returned is
      // expected to be MaxConnectionNumber * MaxConnectionNumber
      if (count == MaxConnectionNumber * MaxConnectionNumber)
      {
         Console.WriteLine("Received all replies.");
         Console.WriteLine("Press any key to exit.");
      }
   }
}

The overridden OnMessage implementation counts the number of received messages and every 10,000 messages outputs the number of messages received and the number of milliseconds elapsed since we started sending messages to the server. Showing these values for every message would be too expensive as it would take much more time than the process of exchanging messages itself.

The next code establishes the client connections and sends the “Hello world!” message to the service endpoint.


			
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void Main (string[] args)
{  
   var clients = new WebSocketClient[MaxConnectionNumber];
             
   // the service instance that will broadcast through the client
   // connections and receive inbound replies
   ClientService service = new ClientService();
             
   for (int count=0; count < MaxConnectionNumber; count++)
   {
      // initialize a new client associated with the service instance
      clients[count] = service.CreateClient(
        new Uri("ws://localhost:9090"));
      clients[count].Open();
   }
             
   // start measuring the roundtrip time
   stopwatch.Start();
 
   // broadcast the message to all associated channels asynchronouly
   service.Broadcast("Hello world!");
             
   Console.Read();
}

The code above creates 1,000 client channels by calling service.CreateClient(), with all channels created being associated to a single service instance. This means that the ClientService will handle all client channels and the OnMessage method of the ClientService will handle all inbound messages received through these channels.

The most important part of our sample code is service.Broadcast("Hello world!") whose Broadcast method pushes messages to all active connections associated with the service. By making a single call we send 1,000 “Hello world!” messages, one for each of client connection.

When these messages are received by the server endpoint, they get dispatched to the OnMessage method of the ServerService class. Then each received message is pushed back to every one of the 1,000 client connections.

So we are expecting a massive push back of one million message to be returned to the ClientService.

You can download the sample code from:
http://downloads.noemax.com/samples/PWS/Broadcasting.zip

In this example we used the lower level API of to show the basics of PowerWebSockets. In the next sample we will examine PWS messaging.