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.
01020304050607080910111213using
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.
01020304050607080910111213public
static
void
Main (
string
[] args)
{
Console
.WriteLine (
"Starting the server.."
);
var
server =
new
WebSocketServer<ServerService>();
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.
010203040506070809101112131415161718192021222324252627282930313233343536using
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.
010203040506070809101112131415161718192021222324public
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(
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