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.
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.
"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();
Using the plugin, we can register to call arbitrary Javascript functions when any of several events occurs.
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!"); });
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.
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
'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.
'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.
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.
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.
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 callcreateThread
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.
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.
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.
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.
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.
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
.