| 1 |
liveuser |
1 |
WebSocket Client & Server Implementation for Node
|
|
|
2 |
=================================================
|
|
|
3 |
|
|
|
4 |
[](http://badge.fury.io/js/websocket)
|
|
|
5 |
|
|
|
6 |
[](https://www.npmjs.com/package/websocket)
|
|
|
7 |
|
|
|
8 |
[](https://nodei.co/npm/websocket/)
|
|
|
9 |
|
|
|
10 |
[](https://nodei.co/npm/websocket/)
|
|
|
11 |
|
|
|
12 |
[ ](https://codeship.com/projects/61106)
|
|
|
13 |
|
|
|
14 |
Overview
|
|
|
15 |
--------
|
|
|
16 |
This is a (mostly) pure JavaScript implementation of the WebSocket protocol versions 8 and 13 for Node. There are some example client and server applications that implement various interoperability testing protocols in the "test/scripts" folder.
|
|
|
17 |
|
|
|
18 |
For a WebSocket client written in ActionScript 3, see my [AS3WebScocket](https://github.com/theturtle32/AS3WebSocket) project.
|
|
|
19 |
|
|
|
20 |
|
|
|
21 |
Documentation
|
|
|
22 |
=============
|
|
|
23 |
|
|
|
24 |
[You can read the full API documentation in the docs folder.](docs/index.md)
|
|
|
25 |
|
|
|
26 |
|
|
|
27 |
Changelog
|
|
|
28 |
---------
|
|
|
29 |
|
|
|
30 |
***Current Version: 1.0.23*** — Released 2016-05-18***
|
|
|
31 |
|
|
|
32 |
***Version 1.0.23***
|
|
|
33 |
|
|
|
34 |
* Official support for Node 6.x
|
|
|
35 |
* Updating dependencies. Specifically, updating nan to ^2.3.3
|
|
|
36 |
|
|
|
37 |
***Version 1.0.22***
|
|
|
38 |
|
|
|
39 |
* Updating to work with nan 2.x
|
|
|
40 |
|
|
|
41 |
|
|
|
42 |
***Version 1.0.21***
|
|
|
43 |
|
|
|
44 |
* Incrememnted and re-published to work around an aborted npm publish of v1.0.20.
|
|
|
45 |
|
|
|
46 |
***Version 1.0.20***
|
|
|
47 |
|
|
|
48 |
* Added EventTarget to the W3CWebSocket interface (Thanks, [@ibc](https://github.com/ibc)!)
|
|
|
49 |
* Corrected an inaccurate error message. (Thanks, [@lekoaf](https://github.com/lekoaf)!)
|
|
|
50 |
|
|
|
51 |
***Version 1.0.19***
|
|
|
52 |
|
|
|
53 |
* Updated to nan v1.8.x (tested with v1.8.4)
|
|
|
54 |
* Added `"license": "Apache-2.0"` to package.json via [pull request #199](https://github.com/theturtle32/WebSocket-Node/pull/199) by [@pgilad](https://github.com/pgilad). See [npm1k.org](http://npm1k.org/).
|
|
|
55 |
|
|
|
56 |
[View the full changelog](CHANGELOG.md)
|
|
|
57 |
|
|
|
58 |
Browser Support
|
|
|
59 |
---------------
|
|
|
60 |
|
|
|
61 |
All current browsers are fully supported.
|
|
|
62 |
|
|
|
63 |
* Firefox 7-9 (Old) (Protocol Version 8)
|
|
|
64 |
* Firefox 10+ (Protocol Version 13)
|
|
|
65 |
* Chrome 14,15 (Old) (Protocol Version 8)
|
|
|
66 |
* Chrome 16+ (Protocol Version 13)
|
|
|
67 |
* Internet Explorer 10+ (Protocol Version 13)
|
|
|
68 |
* Safari 6+ (Protocol Version 13)
|
|
|
69 |
|
|
|
70 |
***Safari older than 6.0 is not supported since it uses a very old draft of WebSockets***
|
|
|
71 |
|
|
|
72 |
***If you need to simultaneously support legacy browser versions that had implemented draft-75/draft-76/draft-00, take a look here: https://gist.github.com/1428579***
|
|
|
73 |
|
|
|
74 |
Benchmarks
|
|
|
75 |
----------
|
|
|
76 |
There are some basic benchmarking sections in the Autobahn test suite. I've put up a [benchmark page](http://theturtle32.github.com/WebSocket-Node/benchmarks/) that shows the results from the Autobahn tests run against AutobahnServer 0.4.10, WebSocket-Node 1.0.2, WebSocket-Node 1.0.4, and ws 0.3.4.
|
|
|
77 |
|
|
|
78 |
Autobahn Tests
|
|
|
79 |
--------------
|
|
|
80 |
The very complete [Autobahn Test Suite](http://autobahn.ws/testsuite/) is used by most WebSocket implementations to test spec compliance and interoperability.
|
|
|
81 |
|
|
|
82 |
- [View Server Test Results](http://theturtle32.github.com/WebSocket-Node/test-report/servers/)
|
|
|
83 |
- [View Client Test Results](http://theturtle32.github.com/WebSocket-Node/test-report/clients/)
|
|
|
84 |
|
|
|
85 |
Notes
|
|
|
86 |
-----
|
|
|
87 |
This library has been used in production on [worlize.com](https://www.worlize.com) since April 2011 and seems to be stable. Your mileage may vary.
|
|
|
88 |
|
|
|
89 |
**Tested with the following node versions:**
|
|
|
90 |
|
|
|
91 |
- 6.2.0
|
|
|
92 |
- 5.11.1
|
|
|
93 |
- 4.4.4
|
|
|
94 |
- 0.10.45
|
|
|
95 |
|
|
|
96 |
It may work in earlier or later versions but I'm not actively testing it outside of the listed versions. YMMV.
|
|
|
97 |
|
|
|
98 |
Installation
|
|
|
99 |
------------
|
|
|
100 |
|
|
|
101 |
A few users have reported difficulties building the native extensions without first manually installing node-gyp. If you have trouble building the native extensions, make sure you've got a C++ compiler, and have done `npm install -g node-gyp` first.
|
|
|
102 |
|
|
|
103 |
Native extensions are optional, however, and WebSocket-Node will work even if the extensions cannot be compiled.
|
|
|
104 |
|
|
|
105 |
In your project root:
|
|
|
106 |
|
|
|
107 |
$ npm install websocket
|
|
|
108 |
|
|
|
109 |
Then in your code:
|
|
|
110 |
|
|
|
111 |
```javascript
|
|
|
112 |
var WebSocketServer = require('websocket').server;
|
|
|
113 |
var WebSocketClient = require('websocket').client;
|
|
|
114 |
var WebSocketFrame = require('websocket').frame;
|
|
|
115 |
var WebSocketRouter = require('websocket').router;
|
|
|
116 |
var W3CWebSocket = require('websocket').w3cwebsocket;
|
|
|
117 |
```
|
|
|
118 |
|
|
|
119 |
Note for Windows Users
|
|
|
120 |
----------------------
|
|
|
121 |
Because there is a small C++ component used for validating UTF-8 data, you will need to install a few other software packages in addition to Node to be able to build this module:
|
|
|
122 |
|
|
|
123 |
- [Microsoft Visual C++](http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-cpp-express)
|
|
|
124 |
- [Python 2.7](http://www.python.org/download/) (NOT Python 3.x)
|
|
|
125 |
|
|
|
126 |
|
|
|
127 |
Current Features:
|
|
|
128 |
-----------------
|
|
|
129 |
- Licensed under the Apache License, Version 2.0
|
|
|
130 |
- Protocol version "8" and "13" (Draft-08 through the final RFC) framing and handshake
|
|
|
131 |
- Can handle/aggregate received fragmented messages
|
|
|
132 |
- Can fragment outgoing messages
|
|
|
133 |
- Router to mount multiple applications to various path and protocol combinations
|
|
|
134 |
- TLS supported for outbound connections via WebSocketClient
|
|
|
135 |
- TLS supported for server connections (use https.createServer instead of http.createServer)
|
|
|
136 |
- Thanks to [pors](https://github.com/pors) for confirming this!
|
|
|
137 |
- Cookie setting and parsing
|
|
|
138 |
- Tunable settings
|
|
|
139 |
- Max Receivable Frame Size
|
|
|
140 |
- Max Aggregate ReceivedMessage Size
|
|
|
141 |
- Whether to fragment outgoing messages
|
|
|
142 |
- Fragmentation chunk size for outgoing messages
|
|
|
143 |
- Whether to automatically send ping frames for the purposes of keepalive
|
|
|
144 |
- Keep-alive ping interval
|
|
|
145 |
- Whether or not to automatically assemble received fragments (allows application to handle individual fragments directly)
|
|
|
146 |
- How long to wait after sending a close frame for acknowledgment before closing the socket.
|
|
|
147 |
- [W3C WebSocket API](http://www.w3.org/TR/websockets/) for applications running on both Node and browsers (via the `W3CWebSocket` class).
|
|
|
148 |
|
|
|
149 |
|
|
|
150 |
Known Issues/Missing Features:
|
|
|
151 |
------------------------------
|
|
|
152 |
- No API for user-provided protocol extensions.
|
|
|
153 |
|
|
|
154 |
|
|
|
155 |
Usage Examples
|
|
|
156 |
==============
|
|
|
157 |
|
|
|
158 |
Server Example
|
|
|
159 |
--------------
|
|
|
160 |
|
|
|
161 |
Here's a short example showing a server that echos back anything sent to it, whether utf-8 or binary.
|
|
|
162 |
|
|
|
163 |
```javascript
|
|
|
164 |
#!/usr/bin/env node
|
|
|
165 |
var WebSocketServer = require('websocket').server;
|
|
|
166 |
var http = require('http');
|
|
|
167 |
|
|
|
168 |
var server = http.createServer(function(request, response) {
|
|
|
169 |
console.log((new Date()) + ' Received request for ' + request.url);
|
|
|
170 |
response.writeHead(404);
|
|
|
171 |
response.end();
|
|
|
172 |
});
|
|
|
173 |
server.listen(8080, function() {
|
|
|
174 |
console.log((new Date()) + ' Server is listening on port 8080');
|
|
|
175 |
});
|
|
|
176 |
|
|
|
177 |
wsServer = new WebSocketServer({
|
|
|
178 |
httpServer: server,
|
|
|
179 |
// You should not use autoAcceptConnections for production
|
|
|
180 |
// applications, as it defeats all standard cross-origin protection
|
|
|
181 |
// facilities built into the protocol and the browser. You should
|
|
|
182 |
// *always* verify the connection's origin and decide whether or not
|
|
|
183 |
// to accept it.
|
|
|
184 |
autoAcceptConnections: false
|
|
|
185 |
});
|
|
|
186 |
|
|
|
187 |
function originIsAllowed(origin) {
|
|
|
188 |
// put logic here to detect whether the specified origin is allowed.
|
|
|
189 |
return true;
|
|
|
190 |
}
|
|
|
191 |
|
|
|
192 |
wsServer.on('request', function(request) {
|
|
|
193 |
if (!originIsAllowed(request.origin)) {
|
|
|
194 |
// Make sure we only accept requests from an allowed origin
|
|
|
195 |
request.reject();
|
|
|
196 |
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
|
|
|
197 |
return;
|
|
|
198 |
}
|
|
|
199 |
|
|
|
200 |
var connection = request.accept('echo-protocol', request.origin);
|
|
|
201 |
console.log((new Date()) + ' Connection accepted.');
|
|
|
202 |
connection.on('message', function(message) {
|
|
|
203 |
if (message.type === 'utf8') {
|
|
|
204 |
console.log('Received Message: ' + message.utf8Data);
|
|
|
205 |
connection.sendUTF(message.utf8Data);
|
|
|
206 |
}
|
|
|
207 |
else if (message.type === 'binary') {
|
|
|
208 |
console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
|
|
|
209 |
connection.sendBytes(message.binaryData);
|
|
|
210 |
}
|
|
|
211 |
});
|
|
|
212 |
connection.on('close', function(reasonCode, description) {
|
|
|
213 |
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
|
|
|
214 |
});
|
|
|
215 |
});
|
|
|
216 |
```
|
|
|
217 |
|
|
|
218 |
Client Example
|
|
|
219 |
--------------
|
|
|
220 |
|
|
|
221 |
This is a simple example client that will print out any utf-8 messages it receives on the console, and periodically sends a random number.
|
|
|
222 |
|
|
|
223 |
*This code demonstrates a client in Node.js, not in the browser*
|
|
|
224 |
|
|
|
225 |
```javascript
|
|
|
226 |
#!/usr/bin/env node
|
|
|
227 |
var WebSocketClient = require('websocket').client;
|
|
|
228 |
|
|
|
229 |
var client = new WebSocketClient();
|
|
|
230 |
|
|
|
231 |
client.on('connectFailed', function(error) {
|
|
|
232 |
console.log('Connect Error: ' + error.toString());
|
|
|
233 |
});
|
|
|
234 |
|
|
|
235 |
client.on('connect', function(connection) {
|
|
|
236 |
console.log('WebSocket Client Connected');
|
|
|
237 |
connection.on('error', function(error) {
|
|
|
238 |
console.log("Connection Error: " + error.toString());
|
|
|
239 |
});
|
|
|
240 |
connection.on('close', function() {
|
|
|
241 |
console.log('echo-protocol Connection Closed');
|
|
|
242 |
});
|
|
|
243 |
connection.on('message', function(message) {
|
|
|
244 |
if (message.type === 'utf8') {
|
|
|
245 |
console.log("Received: '" + message.utf8Data + "'");
|
|
|
246 |
}
|
|
|
247 |
});
|
|
|
248 |
|
|
|
249 |
function sendNumber() {
|
|
|
250 |
if (connection.connected) {
|
|
|
251 |
var number = Math.round(Math.random() * 0xFFFFFF);
|
|
|
252 |
connection.sendUTF(number.toString());
|
|
|
253 |
setTimeout(sendNumber, 1000);
|
|
|
254 |
}
|
|
|
255 |
}
|
|
|
256 |
sendNumber();
|
|
|
257 |
});
|
|
|
258 |
|
|
|
259 |
client.connect('ws://localhost:8080/', 'echo-protocol');
|
|
|
260 |
```
|
|
|
261 |
|
|
|
262 |
Client Example using the *W3C WebSocket API*
|
|
|
263 |
--------------------------------------------
|
|
|
264 |
|
|
|
265 |
Same example as above but using the [W3C WebSocket API](http://www.w3.org/TR/websockets/).
|
|
|
266 |
|
|
|
267 |
```javascript
|
|
|
268 |
var W3CWebSocket = require('websocket').w3cwebsocket;
|
|
|
269 |
|
|
|
270 |
var client = new W3CWebSocket('ws://localhost:8080/', 'echo-protocol');
|
|
|
271 |
|
|
|
272 |
client.onerror = function() {
|
|
|
273 |
console.log('Connection Error');
|
|
|
274 |
};
|
|
|
275 |
|
|
|
276 |
client.onopen = function() {
|
|
|
277 |
console.log('WebSocket Client Connected');
|
|
|
278 |
|
|
|
279 |
function sendNumber() {
|
|
|
280 |
if (client.readyState === client.OPEN) {
|
|
|
281 |
var number = Math.round(Math.random() * 0xFFFFFF);
|
|
|
282 |
client.send(number.toString());
|
|
|
283 |
setTimeout(sendNumber, 1000);
|
|
|
284 |
}
|
|
|
285 |
}
|
|
|
286 |
sendNumber();
|
|
|
287 |
};
|
|
|
288 |
|
|
|
289 |
client.onclose = function() {
|
|
|
290 |
console.log('echo-protocol Client Closed');
|
|
|
291 |
};
|
|
|
292 |
|
|
|
293 |
client.onmessage = function(e) {
|
|
|
294 |
if (typeof e.data === 'string') {
|
|
|
295 |
console.log("Received: '" + e.data + "'");
|
|
|
296 |
}
|
|
|
297 |
};
|
|
|
298 |
```
|
|
|
299 |
|
|
|
300 |
Request Router Example
|
|
|
301 |
----------------------
|
|
|
302 |
|
|
|
303 |
For an example of using the request router, see `libwebsockets-test-server.js` in the `test` folder.
|
|
|
304 |
|
|
|
305 |
|
|
|
306 |
Resources
|
|
|
307 |
---------
|
|
|
308 |
|
|
|
309 |
A presentation on the state of the WebSockets protocol that I gave on July 23, 2011 at the LA Hacker News meetup. [WebSockets: The Real-Time Web, Delivered](http://www.scribd.com/doc/60898569/WebSockets-The-Real-Time-Web-Delivered)
|