Introduction
This article describes an example websocket server (which happens to be written in PHP), use of the Sec-WebSocket-Protocol header and an example client in HTML/javascript.
Implementing Protocols allows a single websocket server to present different interfaces to different clients.
Background
Websockets provide a connection between browser and server which allows data to be sent in either direction at any time. There are a number of 'server-push' methods in use but Websockets promises to replace most, if not all, of these 'workarounds'.
The Websockets standard (as per RFC 6455 ) now has native support in most popular desktop and mobile browsers with compatible javascript api - even InternetExplorer (as of IE v11 ).
The basic
frame protocol is described in RFC 6455; a binary header contains an
opcode, length and
mask information followed by a block of data. How that data is interpreted is not defined by the specification, nor is the actual value of an optional http header used in the startup handshake:
Sec-WebSocket-Protocol
Many simple websocket examples simply ignore protocol and use the connection to send a string (maybe encoded as JSON) to some server which is designed to understand it. However, if you happen to connect such a client to another websocket server - almost anything could happen.
Therefore, you can define your own method of interpreting websocket data, call that a protocol, give your protocol a name like 'myprotocol' and then have your javascript open a websocket connection like this:
var host = "ws://some.host.or.other/
var protcol="myprotocol";
socket = new WebSocket(host, protocol);
The server then knows it has to talk 'myprotocol' for this connection.
Actually, a server could be written to handle different data based on the protocol and/or the content of the url since all of this is down to the developer.
What we are looking at here is an example of a single websocket server which can handle several different protocols - allowing different clients to request different formats of data from the same server.
'True' vs. 'Cheating' websocket servers
I'm not sure there really is such a definition, however...
A 'true' websocket server would be integrated with a standard webserver which accepts requests like "http://some.url/" and delivers an HTTP service and accepts requests like "ws://something" and delivers a websocket service - all, usually, on port 80.
A 'cheating' websocket server simply runs and accepts socket connections on a given port number. The example php server below 'cheats' because it can be executed from the commandline or a standard webserver (port 80) and then accepts websocket connections itself on a different port.
The example here is a 'cheating' websocket server for development use. You probably don't want to do this in a live environment
If you want a simple webserver to use with this that you just run-and-it-works; check out Civetweb or Mongoose.
What does the code do?
websocket2.php
websocket2.php is an example websocket server written in php, you can run this on the commandline if you have php installed or run it from a local webserver. It is quite happy accepting connections from anywhere on the web as long as you configure your routers etc. to allow its listening port number thru.
It is written to only accept connections with a valid protocol. If the javascript in our browser asked for:
socket = new WebSocket(host, 'myprotocol');
then, looking at the headers on connect with Chrome's developer tool (Network/headers), we see:
Request URL:ws:
Request Method:GET
Status Code:101 Switching Protocols
Request Headers
Cache-Control:no-cache
Connection:Upgrade
Host:tonywilk.no-ip.org:12352
Origin:http:
Pragma:no-cache
Sec-WebSocket-Key:DMF3ByMTLq+cp7AyMN0qUA==
Sec-WebSocket-Protocol:myprotocol <-- browser sends 'can I have this protocol'
Sec-WebSocket-Version:13
Upgrade:websocket
User-Agent: ... Chrome/32.0.1700.102 Safari/537.36
Response Headers
Connection:Upgrade
Sec-WebSocket-Accept:L6wqtsHk6dzD+kd9NCYT6Wt7OCU=
Sec-WebSocket-Protocol:myprotocol <-- server replies ok
Upgrade:WebSocket
In fact the client can request a number of protocols like this:
Sec-WebSocket-Protocol:myprotocolv1,myprotocolv2,anotherprotcol
Allowing the server to decide which one to provide,
Our example server code has a list of handlers, one for each protocol type:
$protocolHandlers= array(
"echo" => 'doEcho', // simply echos payload to ALL clients
"chat" => 'doChat', // sends "[name] message..." to all other 'chat' clients
"command" => 'doCommand', // accepts commands to the server
);
include('./JSONsvc2.php'); // JSONsvc: adds protocol handler "JSONsvc"
(The included JSONsvc2.php dynamically adds "JSONsvc" to this list.)
These example protocols are very simple, but look at the differences - which hopefully demonstrate the usefulness of different protocols at the server end - if only to separate code and development of alternate interfaces to the same core server and be able to talk to all clients easily.
The JSONsvc protocol is a little more complicated and will be covered in a later article.
(In the mean time, there's lots of comment in the source.)
websocket2.html
An example client which connects to the server using any of its protocols. it has a HELP button
If this is placed on a webserver along with the php files it can start the php server by loading it into an invisible iframe or you can run the php server on some socket somewhere else and just fill in the relevant host ip:port information. The php server attempts to keep the socket open by sending a websocket ping every 20 seconds which the javascript api helpfully replies to.
The default port number for the websocket server is 12352. This can be changed on the commandline or in the url (see the source for details).
Using the Code
Extract the .zip into some directory 'wsdemo'.
If this directory is on a local webserver with php available, you are good to go - just browse to http://myserver/wsdemo/websockets2.html
- assuming that your access to myserver
allows access to port 12352.
From the browser you have to set the location of the php script if you want the page to start it for you by entering:
php script url: http:
to run on a different port:
php script url: http:
or you can run the php in a browser window with debug by opening a browser with:
http:
If the directory is on your local machine, you will have to get PHP installed then you can run websockets2.php
from the commandline and open websockets2.html
in a browser.
Note that websocket2.php
requires JSONsvc2.php
.
On the commandline you can change the default port from 12352 amd enable debug by:
prompt> php websockets2.php -d -p9999
In all cases, the browser app needs to know where the websocket server is located, so fill in the Websocket Host. some examples:
ws:
The defaults are to the webserver which sits on my desk, so you can try simply browsing to <a href="http://tonywilk.no-ip.org/wsdemo/websocket2.html" target="_blank" title="http://tonywilk.no-ip.org/wsdemo/websocket2.html">http://tonywilk.no-ip.org/wsdemo/websocket2.html</a>
- this may or may not be available, but it's worth a try !
Finally
I think we're going to see a lot more of Websockets being used in all sorts of web applications now that we have compatibility with most browsers. However the current version is still young and some parts are causing security concerns (like the data masking to prevent cache poisoning - which is, frankly, pathetic), so I have no doubt it will change before too long.
There may even be standardized protocols for use with Websockets eventually.
In the mean time, get hold of the code, run up a server, open a browser and have a play!
TonyWilk
Notes
Browsers supporting Websockets v13
At the time of writing the following browsers have been tested with this code:
PC: Internet Explorer 11, Chrome 32, Firefox 26.0 and Android: Chrome 31, Opera 18
on windows pc/laptop, Samsung S3/4, Amazon Fire and a Nexus 7
Websocket Standard
The Websocket standard defines "Sec-WebSocket-Version: 13", if you see references to higher version numbers - check if they mean the earler drafts. The document which became "The Websocket Protocol" version 13 was called: "draft-ietf-hybi-thewebsocketprotocol-17" (!)