SockIt · Full Tutorial

Download



Home · Quick Tutorial · Full Tutorial · Demos · API · Source Documentation · Developers

Initialization

The plugin allows Javascript applications to perform asynchronous network I/O using TCP or UDP. To begin, load the plugin into the page by calling:
	var sockit = loadSockitPlugin();
This function is found in sockit.js. Once loadSockitPlugin has been called, you can create a TCP or UDP server or client, and asynchronously communicate using Javascript event callbacks.

Server

To create a client, we must minimally specify the hostname and port to which the client will connect. This hostname and port are permanent for the client, so that a client is bound to a single remote endpoint. To create a UDP server that will listen on port 1234, we simply create it:
	var server = sockit.createUdpServer(1234);
And tell it to start bind to the given port and start listening:
	server.listen();
Now, suppose we are finished with this server, and would like to free the port and associated resources:
	server.close();
Now, the server finishes sending any necessary responses, and gracefully shuts down.

Client

To create a TCP client to connect to "www.example.com" on port 12345, we first create a client:
	var client = sockit.createTcpClient("www.example.com", 12345);
Now, let's send some data over the wire:
	client.send("Some data");
To send structured data across the connection, we simply flatten the data to a string. For instance, to send some data structure myDataStructure, we could first convert it into JSON:
	client.send(JSON.stringify(myDataStructure));
Once we are finished with our client, we can gracefully shut it down. This is performed asynchronously, so that all send calls complete before the client shuts down.
	client.close();

Registering Callbacks

Using the plugin, we can register to call arbitrary Javascript functions when any of several events occurs.

Registering 'Data Received' Callbacks

On either clients or servers, we can register callbacks to be invoked when any data is received on the connection. Assuming we already have a TCP (or UDP) server myServer listening on some port, we can log all data received with:

	myServer.addEventListener('data', function(event) {
                var data = event.read();
		console.log("Received: " + data);
	});

Likewise, functions that handle 'data' functions should receive an event object, with which we can read the data received, reply to any data received, or get information about the remote endpoint. For instance, to have myServer also reply to every message received with an acknowledgement, we simply change the previous code to the following:

	myServer.addEventListener('data', function(event) {
                var message = event.read();
		console.log("Received: " + message);
		event.send("Got your message!");
		
	});

Registering 'Error' Callbacks

On either clients or servers, we can register a callback to be invoked when an error occurs in an object. For instance, suppose we have some client, myErrorProneClient, and would like to log any errors on that object to the browser console. We can do so with the following:

	myErrorProneClient.addEventListener('error', function(message) {
		console.log("Error: " + message);
		// Error handle
	});

When an error occurs, an event is fired which contains the error message as a parameter, so that it can be used for debugging as shown above.

Registering 'Shutdown' Callbacks

Since all I/O is performed asynchronously, calling shutdown on a server or client may not immediately complete, but will be executed once any data waiting to be sent has been sent. Suppose we want to be notified when some server, say myOldServer, has completely shutdown and closed its socket. We can do this by registering a callback on a 'close' event, which provides no parameters, as shown below:

	myOldServer.addEventListener('close', function() {
		console.log("My old server finally shutdown!");
		// Cleanup
	});
Note that shutdown callbacks will not be performed when the page is refreshed

Registering 'Resolve' Callbacks

When we create a client, it will asynchronously resolve the remote endpoint. To execute a function once the client has successfully performed the DNS resolution, we register the 'resolve' callback:
	server.addEventListener('resolve', function() {
		console.log("Remote endpoint successfully resolved!");
		// Do stuff
	});
This callback can only be registered on a client object, as it is fired from the client once has resolved the remote endpoint.

Registering 'Open' Callbacks

When creating a server using the plugin, the server may not immediately begin listening for incoming connections. To execute a function once a server has been initialized and opened, we register the 'open' callback:
	server.addEventListener('open', function() {
		console.log("Server is now listening!");
		// Do stuff
	});
This callback only applies to the server, as it is fired once the server has bound to its listening port and started listening for incoming connections.

Registering 'Disconnect' Callbacks

For TCP clients and servers we can register a callback to occur whenever the client or server has disconnect from the remote host:

	myTcpClientOrServer.addEventListener('disconnect', function(message) {
		console.log("My TCP object has been disconnected! Error message: " + message);
		// Error handle
	});

Thus, when a TCP client or server has disconnected from some remote host, an event is fired which contains the error message as a parameter, so that it can be used for debugging as shown above.

Registering 'Connect' Callbacks

For TCP clients or servers we can register a callback to occur whenever the client or server has connected to a remote host:

	myTcpClientOrServer.addEventListener('connect', function() {
		console.log("My TCP client or server has been connected!");
		// Do stuff
	});

When a TCP client or server has connected to some remote host, an event is fired which contain no parameters.

Controlling Threading

To gain tighter control over resources used by the plugin, and better control the performance and interaction between clients or servers, we can manually create thread objects. These thread objects expose the same methods as does the top level API, but each each thread represents a separate thread of computation.

Behind the scenes, each thread object actually consists of two threads of computation: first, the foreground that represents the main thread of computation of the browser, and second, a worker thread that executes I/O requests made by the foreground thead. While each thread object shares the foreground thread, the power of controlling threading comes from the background worker thread, which is unique to each thread object, so that I/O requests from a thread object executes in parallel to I/O requests from any other thread object.

Actions performed on each thread are still asynchronous, but actions running on separate threads may execute in parallel, while actions executed on a single thread will be asynchronous, but will not execute in parallel. Using the top level API for the plugin rather than creating thread objects uses a default background thread, so that actions called from the root API may be executed in parallel with actions called from an explicitly created thread.

To create a new network thread, simply call createThread from the plugin root:
	var myThread = sockit.createThread();
Then, we can create clients or servers on this thread, and actions invoked on these objects will be executed in this thread:
	var anotherTcpServer = myThread.createTcpServer(1234);
Likewise, all other server and client initialization methods that exist on the top level API are mirrored on the thread objects, and on each thread, we can create any number of servers and clients.

Using Additional Socket Options

In order to specify options on the underlying TCP and UDP sockets of the plugin, servers and clients can be created with several optional arguments. Arguments that are not included revert to their default value in each client and server.

A Multicast UDP Server

Suppose we want to create a UDP server that will receive messages from multicast group DEV.SockIt.DEMO, which resolves to 239.8.128.34, port 54321. Then, we simply do the following:

	var multicastUdpServer = sockit.createUdpServer('localhost', 54321, {
		multicast	:   true,
		multicastGroup	:   "239.8.128.34",
		reuseAddress	:   true
	});
	
	multicastUdpServer.listen();

Additionally, if we plan to reply from this server, we should be sure to set the MulticastTTL parameter, since this has no specified default value. Likewise, for a multicast server such as in this example, we should always set ReuseAddress to be true, so that multiple servers may listen to the same port.

A Multicast UDP Client

Suppose we want to create a UDP client that will multicast to a multicast group DEV.SockIt.DEMO which is bound to 239.8.128.34, port 9999. Then, to create a client to send a multicast message to this group, with a TTL of 16, we simply do the following:

	var multicastUdpClient = sockit.createUdpClient('239.8.128.34', 9999, {
		multicast	:   true,
		multicastTTL	:   16
	});
	
	multicastUdpClient.send("Hello!");

Note that when using multicast, we should always be sure to include both the Multicast and MulticastTTL parameters for sending to a multicast group such as in this example.

IPv6 TCP Client

Suppose we want to create a TCP client to ::1 on port 8888, that will use IPv6, and request to send keep-alive messages over its connection every 100ms. Then, we can do this with the following:

	var tcpClient = sockit.createTcpClient('::1', 8888, {
	        keepAliveTimeout : 100,
	        keepAlive :   true,     
		ipv6  	  :   true
	});

For a full list of the available options for each client and server, see our full API documentation.

Binary Data

Suppose we want to use a TCP client connected to google.com:80 to implement a new protocol, where we must start each message with the byte 0xFF, followed by a single byte containing the message length, then the message itself. Although this is typically difficult using Javascript, to do this using the client API, we simply do the following:

    var binaryTcpClient = sockit.createTcpClient('google.com', 80);
    binaryTcpClient.sendBytes([0xFF, message.length]);
    binaryTcpClient.send(message);

Alternatively, we could have used the top level API to convert the bytes into string data, and used the typical client send to send the result:

    var binaryTcpClient = sockit.createTcpClient('google.com', 80);
    var stringData = sockit.toBinary([0xFF, message.length]);
    binaryTcpClient.send(stringData + message);

Note that here, we assume that message.length is at most 255.

 

Home · Quick Tutorial · Full Tutorial · Demos · API · Source Documentation · Developers