Quantcast
Channel: nugget Wiki Rss Feed
Viewing all articles
Browse latest Browse all 16

Updated Wiki: 02 SubProtocol

$
0
0

Sample 02 - SubProtocol

The web socket protocol has support for so-called sub-protocols. These are protocols that you yourself define and with Nugget they can be used to send "models" between the browser and the server.
Typically the data you send between the server and the browser would be JSON but it could be on any format. In the app on the server you define a model factory that analyses the data coming from the browser and wraps it in an object of a specified type, this is then passed on to the socket handler.

The sample contains two files: client.html and Server.cs, they represent the client and the server respectively.

client.html

Like in sample 01 this file contains the javascript:
ws = new WebSocket('ws://localhost:8181/subsample', 'post');

ws.onmessage = function (evt) {
	debug.innerHTML += evt.data + '<br/>';
};

ws.onopen = function () {
	debug.innerHTML += '.. connection open<br/>';
};

ws.onclose = function () {
	debug.innerHTML += '.. connection closed<br/>';
}
The above isn't very different from the javascript in sample 01, except that in this sample the web socket connects to the server using a sub protocol "post".

The file also contains some input fields, and some javascript used to send data to the server:
<inputtype="text"name="name"id="name"placeholder="name"/><br/><textareaid="message"cols="50"rows="5"placeholder="message"></textarea><br/><inputtype="button"value="Send"id="submit_button"onclick="clicks()"/>
var clicks = function () {
	// get the author and the message bodyvar name = document.getElementById('name').value;
	var msg = document.getElementById('message').value;
	// create a json stringvar json = JSON.stringify({ author: name, body: msg });
	debug.innerHTML += "sending " + json + "<br/>";
	// send it
	ws.send(json);
}

Server.cs

Like in sample 01 we are using a handler class to handle the connection server-side:
// the handler class// note that the class inherits the generic interface and uses the model as the type parameterclass PostSocket : WebSocket<Post>
{
	// this method is called when data is comming from the client// note that the method takes a Post object instead of a stringpublicoverridevoid Incomming(Post post)
	{
		Console.WriteLine("{0} posted {1}", post.Author, post.Body);
	}

	publicoverridevoid Disconnected()
	{
		Console.WriteLine("--- disconnected ---");
	}

	publicoverridevoid Connected(ClientHandshake handshake)
	{
		Console.WriteLine("--- connected ---");
	}
}
This time however, the class uses the generic interface and a "model"-class as type argument. The model:
// a "model" representing a post made by someoneclass Post
{
	publicstring Author { get; set; }
	publicstring Body { get; set; }

	publicbool IsValid()
	{
		return !String.IsNullOrEmpty(Author) && 
			   !String.IsNullOrEmpty(Body);
	}
}
The handler class now gets an object of the type Post instead of just a string. In order to create the model, we need to register a model factory:
// the model factory// this class is used to convert the data coming from the client into a model objectclass PostFactory : ISubProtocolModelFactory<Post>
{
	// create a new model// "data" is the data comming from the client// "connection" is an object representing the connection to the client, it can be used to identify the client if neededpublic Post Create(string data, WebSocketConnection connection)
	{
		// parse the data (we assume that the data string is on json format)var js = JSON.Parse(data);
		if (js.hasOwnProperty("author") && js.hasOwnProperty("body"))
		{
			// create a new model using the data from the client// "return" passes the model on to the handler classreturnnew Post() { Author = js.author, Body = js.body };
		}
		returnnull;
	}

	// this method is used to define valid models// if a model is not valid, then it is not passed on to the handler class// this method is called internally in the server before the model is passed onpublicbool IsValid(Post p)
	{
		
		if (p == null)
			returnfalse;
		elsereturn p.IsValid();
	}
}
The factory implements the interface ISubProtocolModelFactory<>, this interface specifies two methods:
publicinterface ISubProtocolModelFactory<TModel>
{
	TModel Create(string data, WebSocketConnection connection);
	bool IsValid(TModel model);
}
Create, should create the model based on the string coming from the client, a connection object is also mad available, if the factory needs to identify the client.

IsValid, should return true for valid models and false for invalid models. This method is used to determine whether or not to pass the object along to the handler class. If Create, creates a model that is invalid (null in this case) the model is not passed on to the handler class.

In a sense you jam a "parser" in between the browser and the server. The model factory (the "parser") reads, validates and formats the data coming from the browser, before passing it on to the handler class.

The handler classes can have multiple Incoming methods defined, by implementing the IWebSocket<> interface.
class MyHandler : WebSocket<MyModel>, IWebSocket<MyOtherModel> 
{
	public overide Incoming(MyModel mm) { /* ... */ }
	public Incoming(MyOtherModel mom) { /* ... */ }
The method to call is selected based on the sub protocol used by the browser and the type of the model created by the model factory.

The model factory is registered with the following line:
nugget.SetSubProtocolModelFactory(new PostFactory(), "post");

Where the string specifies which sub protocol to use the factory for.

Viewing all articles
Browse latest Browse all 16


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>