root / HServer / 00.Server / 00.Program / node_modules / engine.io / README.md
이력 | 보기 | 이력해설 | 다운로드 (20.1 KB)
1 |
|
---|---|
2 |
# Engine.IO: the realtime engine |
3 |
|
4 |
[](http://travis-ci.org/socketio/engine.io) |
5 |
[](http://badge.fury.io/js/engine.io) |
6 |
|
7 |
`Engine.IO` is the implementation of transport-based |
8 |
cross-browser/cross-device bi-directional communication layer for |
9 |
[Socket.IO](http://github.com/socketio/socket.io). |
10 |
|
11 |
## How to use |
12 |
|
13 |
### Server |
14 |
|
15 |
#### (A) Listening on a port |
16 |
|
17 |
```js |
18 |
var engine = require('engine.io'); |
19 |
var server = engine.listen(80); |
20 |
|
21 |
server.on('connection', function(socket){ |
22 |
socket.send('utf 8 string'); |
23 |
socket.send(new Buffer([0, 1, 2, 3, 4, 5])); // binary data |
24 |
}); |
25 |
``` |
26 |
|
27 |
#### (B) Intercepting requests for a http.Server |
28 |
|
29 |
```js |
30 |
var engine = require('engine.io'); |
31 |
var http = require('http').createServer().listen(3000); |
32 |
var server = engine.attach(http); |
33 |
|
34 |
server.on('connection', function (socket) { |
35 |
socket.on('message', function(data){ }); |
36 |
socket.on('close', function(){ }); |
37 |
}); |
38 |
``` |
39 |
|
40 |
#### (C) Passing in requests |
41 |
|
42 |
```js |
43 |
var engine = require('engine.io'); |
44 |
var server = new engine.Server(); |
45 |
|
46 |
server.on('connection', function(socket){ |
47 |
socket.send('hi'); |
48 |
}); |
49 |
|
50 |
// … |
51 |
httpServer.on('upgrade', function(req, socket, head){ |
52 |
server.handleUpgrade(req, socket, head); |
53 |
}); |
54 |
httpServer.on('request', function(req, res){ |
55 |
server.handleRequest(req, res); |
56 |
}); |
57 |
``` |
58 |
|
59 |
### Client |
60 |
|
61 |
```html |
62 |
<script src="/path/to/engine.io.js"></script> |
63 |
<script> |
64 |
var socket = new eio.Socket('ws://localhost/'); |
65 |
socket.on('open', function(){ |
66 |
socket.on('message', function(data){}); |
67 |
socket.on('close', function(){}); |
68 |
}); |
69 |
</script> |
70 |
``` |
71 |
|
72 |
For more information on the client refer to the |
73 |
[engine-client](http://github.com/learnboost/engine.io-client) repository. |
74 |
|
75 |
## What features does it have? |
76 |
|
77 |
- **Maximum reliability**. Connections are established even in the presence of: |
78 |
- proxies and load balancers. |
79 |
- personal firewall and antivirus software. |
80 |
- for more information refer to **Goals** and **Architecture** sections |
81 |
- **Minimal client size** aided by: |
82 |
- lazy loading of flash transports. |
83 |
- lack of redundant transports. |
84 |
- **Scalable** |
85 |
- load balancer friendly |
86 |
- **Future proof** |
87 |
- **100% Node.JS core style** |
88 |
- No API sugar (left for higher level projects) |
89 |
- Written in readable vanilla JavaScript |
90 |
|
91 |
## API |
92 |
|
93 |
### Server |
94 |
|
95 |
<hr><br> |
96 |
|
97 |
#### Top-level |
98 |
|
99 |
These are exposed by `require('engine.io')`: |
100 |
|
101 |
##### Events |
102 |
|
103 |
- `flush` |
104 |
- Called when a socket buffer is being flushed. |
105 |
- **Arguments** |
106 |
- `Socket`: socket being flushed |
107 |
- `Array`: write buffer |
108 |
- `drain` |
109 |
- Called when a socket buffer is drained |
110 |
- **Arguments** |
111 |
- `Socket`: socket being flushed |
112 |
|
113 |
##### Properties |
114 |
|
115 |
- `protocol` _(Number)_: protocol revision number |
116 |
- `Server`: Server class constructor |
117 |
- `Socket`: Socket class constructor |
118 |
- `Transport` _(Function)_: transport constructor |
119 |
- `transports` _(Object)_: map of available transports |
120 |
|
121 |
##### Methods |
122 |
|
123 |
- `()` |
124 |
- Returns a new `Server` instance. If the first argument is an `http.Server` then the |
125 |
new `Server` instance will be attached to it. Otherwise, the arguments are passed |
126 |
directly to the `Server` constructor. |
127 |
- **Parameters** |
128 |
- `http.Server`: optional, server to attach to. |
129 |
- `Object`: optional, options object (see `Server#constructor` api docs below) |
130 |
|
131 |
The following are identical ways to instantiate a server and then attach it. |
132 |
```js |
133 |
var httpServer; // previously created with `http.createServer();` from node.js api. |
134 |
|
135 |
// create a server first, and then attach |
136 |
var eioServer = require('engine.io').Server(); |
137 |
eioServer.attach(httpServer); |
138 |
|
139 |
// or call the module as a function to get `Server` |
140 |
var eioServer = require('engine.io')(); |
141 |
eioServer.attach(httpServer); |
142 |
|
143 |
// immediately attach |
144 |
var eioServer = require('engine.io')(httpServer); |
145 |
``` |
146 |
|
147 |
- `listen` |
148 |
- Creates an `http.Server` which listens on the given port and attaches WS |
149 |
to it. It returns `501 Not Implemented` for regular http requests. |
150 |
- **Parameters** |
151 |
- `Number`: port to listen on. |
152 |
- `Object`: optional, options object |
153 |
- `Function`: callback for `listen`. |
154 |
- **Options** |
155 |
- All options from `Server.attach` method, documented below. |
156 |
- **Additionally** See Server `constructor` below for options you can pass for creating the new Server |
157 |
- **Returns** `Server` |
158 |
- `attach` |
159 |
- Captures `upgrade` requests for a `http.Server`. In other words, makes |
160 |
a regular http.Server WebSocket-compatible. |
161 |
- **Parameters** |
162 |
- `http.Server`: server to attach to. |
163 |
- `Object`: optional, options object |
164 |
- **Options** |
165 |
- All options from `Server.attach` method, documented below. |
166 |
- **Additionally** See Server `constructor` below for options you can pass for creating the new Server |
167 |
- **Returns** `Server` a new Server instance. |
168 |
|
169 |
<hr><br> |
170 |
|
171 |
#### Server |
172 |
|
173 |
The main server/manager. _Inherits from EventEmitter_. |
174 |
|
175 |
##### Events |
176 |
|
177 |
- `connection` |
178 |
- Fired when a new connection is established. |
179 |
- **Arguments** |
180 |
- `Socket`: a Socket object |
181 |
|
182 |
##### Properties |
183 |
|
184 |
**Important**: if you plan to use Engine.IO in a scalable way, please |
185 |
keep in mind the properties below will only reflect the clients connected |
186 |
to a single process. |
187 |
|
188 |
- `clients` _(Object)_: hash of connected clients by id. |
189 |
- `clientsCount` _(Number)_: number of connected clients. |
190 |
|
191 |
##### Methods |
192 |
|
193 |
- **constructor** |
194 |
- Initializes the server |
195 |
- **Parameters** |
196 |
- `Object`: optional, options object |
197 |
- **Options** |
198 |
- `pingTimeout` (`Number`): how many ms without a pong packet to |
199 |
consider the connection closed (`60000`) |
200 |
- `pingInterval` (`Number`): how many ms before sending a new ping |
201 |
packet (`25000`) |
202 |
- `upgradeTimeout` (`Number`): how many ms before an uncompleted transport upgrade is cancelled (`10000`) |
203 |
- `maxHttpBufferSize` (`Number`): how many bytes or characters a message |
204 |
can be, before closing the session (to avoid DoS). Default |
205 |
value is `10E7`. |
206 |
- `allowRequest` (`Function`): A function that receives a given handshake |
207 |
or upgrade request as its first parameter, and can decide whether to |
208 |
continue or not. The second argument is a function that needs to be |
209 |
called with the decided information: `fn(err, success)`, where |
210 |
`success` is a boolean value where false means that the request is |
211 |
rejected, and err is an error code. |
212 |
- `transports` (`<Array> String`): transports to allow connections |
213 |
to (`['polling', 'websocket']`) |
214 |
- `allowUpgrades` (`Boolean`): whether to allow transport upgrades |
215 |
(`true`) |
216 |
- `perMessageDeflate` (`Object|Boolean`): parameters of the WebSocket permessage-deflate extension |
217 |
(see [ws module](https://github.com/einaros/ws) api docs). Set to `false` to disable. (`true`) |
218 |
- `threshold` (`Number`): data is compressed only if the byte size is above this value (`1024`) |
219 |
- `httpCompression` (`Object|Boolean`): parameters of the http compression for the polling transports |
220 |
(see [zlib](http://nodejs.org/api/zlib.html#zlib_options) api docs). Set to `false` to disable. (`true`) |
221 |
- `threshold` (`Number`): data is compressed only if the byte size is above this value (`1024`) |
222 |
- `cookie` (`String|Boolean`): name of the HTTP cookie that |
223 |
contains the client sid to send as part of handshake response |
224 |
headers. Set to `false` to not send one. (`io`) |
225 |
- `cookiePath` (`String|Boolean`): path of the above `cookie` |
226 |
option. If false, no path will be sent, which means browsers will only send the cookie on the engine.io attached path (`/engine.io`). |
227 |
Set false to not save io cookie on all requests. (`/`) |
228 |
- `cookieHttpOnly` (`Boolean`): If `true` HttpOnly io cookie cannot be accessed by client-side APIs, such as JavaScript. (`true`) _This option has no effect if `cookie` or `cookiePath` is set to `false`._ |
229 |
- `wsEngine` (`String`): what WebSocket server implementation to use. Specified module must conform to the `ws` interface (see [ws module api docs](https://github.com/websockets/ws/blob/master/doc/ws.md)). Default value is `uws` (see [µWebSockets](https://github.com/uWebSockets/uWebSockets)). |
230 |
- `initialPacket` (`Object`): an optional packet which will be concatenated to the handshake packet emitted by Engine.IO. |
231 |
- `close` |
232 |
- Closes all clients |
233 |
- **Returns** `Server` for chaining |
234 |
- `handleRequest` |
235 |
- Called internally when a `Engine` request is intercepted. |
236 |
- **Parameters** |
237 |
- `http.IncomingMessage`: a node request object |
238 |
- `http.ServerResponse`: a node response object |
239 |
- **Returns** `Server` for chaining |
240 |
- `handleUpgrade` |
241 |
- Called internally when a `Engine` ws upgrade is intercepted. |
242 |
- **Parameters** (same as `upgrade` event) |
243 |
- `http.IncomingMessage`: a node request object |
244 |
- `net.Stream`: TCP socket for the request |
245 |
- `Buffer`: legacy tail bytes |
246 |
- **Returns** `Server` for chaining |
247 |
- `attach` |
248 |
- Attach this Server instance to an `http.Server` |
249 |
- Captures `upgrade` requests for a `http.Server`. In other words, makes |
250 |
a regular http.Server WebSocket-compatible. |
251 |
- **Parameters** |
252 |
- `http.Server`: server to attach to. |
253 |
- `Object`: optional, options object |
254 |
- **Options** |
255 |
- `path` (`String`): name of the path to capture (`/engine.io`). |
256 |
- `destroyUpgrade` (`Boolean`): destroy unhandled upgrade requests (`true`) |
257 |
- `destroyUpgradeTimeout` (`Number`): milliseconds after which unhandled requests are ended (`1000`) |
258 |
- `handlePreflightRequest` (`Boolean|Function`): whether to let engine.io handle the OPTIONS requests. You can also pass a custom function to handle the requests (`true`) |
259 |
- `generateId` |
260 |
- Generate a socket id. |
261 |
- Overwrite this method to generate your custom socket id. |
262 |
- **Parameters** |
263 |
- `http.IncomingMessage`: a node request object |
264 |
- **Returns** A socket id for connected client. |
265 |
|
266 |
<hr><br> |
267 |
|
268 |
#### Socket |
269 |
|
270 |
A representation of a client. _Inherits from EventEmitter_. |
271 |
|
272 |
##### Events |
273 |
|
274 |
- `close` |
275 |
- Fired when the client is disconnected. |
276 |
- **Arguments** |
277 |
- `String`: reason for closing |
278 |
- `Object`: description object (optional) |
279 |
- `message` |
280 |
- Fired when the client sends a message. |
281 |
- **Arguments** |
282 |
- `String` or `Buffer`: Unicode string or Buffer with binary contents |
283 |
- `error` |
284 |
- Fired when an error occurs. |
285 |
- **Arguments** |
286 |
- `Error`: error object |
287 |
- `flush` |
288 |
- Called when the write buffer is being flushed. |
289 |
- **Arguments** |
290 |
- `Array`: write buffer |
291 |
- `drain` |
292 |
- Called when the write buffer is drained |
293 |
- `packet` |
294 |
- Called when a socket received a packet (`message`, `ping`) |
295 |
- **Arguments** |
296 |
- `type`: packet type |
297 |
- `data`: packet data (if type is message) |
298 |
- `packetCreate` |
299 |
- Called before a socket sends a packet (`message`, `pong`) |
300 |
- **Arguments** |
301 |
- `type`: packet type |
302 |
- `data`: packet data (if type is message) |
303 |
|
304 |
##### Properties |
305 |
|
306 |
- `id` _(String)_: unique identifier |
307 |
- `server` _(Server)_: engine parent reference |
308 |
- `request` _(http.IncomingMessage)_: request that originated the Socket |
309 |
- `upgraded` _(Boolean)_: whether the transport has been upgraded |
310 |
- `readyState` _(String)_: opening|open|closing|closed |
311 |
- `transport` _(Transport)_: transport reference |
312 |
|
313 |
##### Methods |
314 |
|
315 |
- `send`: |
316 |
- Sends a message, performing `message = toString(arguments[0])` unless |
317 |
sending binary data, which is sent as is. |
318 |
- **Parameters** |
319 |
- `String` | `Buffer` | `ArrayBuffer` | `ArrayBufferView`: a string or any object implementing `toString()`, with outgoing data, or a Buffer or ArrayBuffer with binary data. Also any ArrayBufferView can be sent as is. |
320 |
- `Object`: optional, options object |
321 |
- `Function`: optional, a callback executed when the message gets flushed out by the transport |
322 |
- **Options** |
323 |
- `compress` (`Boolean`): whether to compress sending data. This option might be ignored and forced to be `true` when using polling. (`true`) |
324 |
- **Returns** `Socket` for chaining |
325 |
- `close` |
326 |
- Disconnects the client |
327 |
- **Returns** `Socket` for chaining |
328 |
|
329 |
### Client |
330 |
|
331 |
<hr><br> |
332 |
|
333 |
Exposed in the `eio` global namespace (in the browser), or by |
334 |
`require('engine.io-client')` (in Node.JS). |
335 |
|
336 |
For the client API refer to the |
337 |
[engine-client](http://github.com/learnboost/engine.io-client) repository. |
338 |
|
339 |
## Debug / logging |
340 |
|
341 |
Engine.IO is powered by [debug](http://github.com/visionmedia/debug). |
342 |
In order to see all the debug output, run your app with the environment variable |
343 |
`DEBUG` including the desired scope. |
344 |
|
345 |
To see the output from all of Engine.IO's debugging scopes you can use: |
346 |
|
347 |
``` |
348 |
DEBUG=engine* node myapp |
349 |
``` |
350 |
|
351 |
## Transports |
352 |
|
353 |
- `polling`: XHR / JSONP polling transport. |
354 |
- `websocket`: WebSocket transport. |
355 |
|
356 |
## Plugins |
357 |
|
358 |
- [engine.io-conflation](https://github.com/EugenDueck/engine.io-conflation): Makes **conflation and aggregation** of messages straightforward. |
359 |
|
360 |
## Support |
361 |
|
362 |
The support channels for `engine.io` are the same as `socket.io`: |
363 |
- irc.freenode.net **#socket.io** |
364 |
- [Google Groups](http://groups.google.com/group/socket_io) |
365 |
- [Website](http://socket.io) |
366 |
|
367 |
## Development |
368 |
|
369 |
To contribute patches, run tests or benchmarks, make sure to clone the |
370 |
repository: |
371 |
|
372 |
``` |
373 |
git clone git://github.com/LearnBoost/engine.io.git |
374 |
``` |
375 |
|
376 |
Then: |
377 |
|
378 |
``` |
379 |
cd engine.io |
380 |
npm install |
381 |
``` |
382 |
|
383 |
## Tests |
384 |
|
385 |
Tests run with `npm test`. It runs the server tests that are aided by |
386 |
the usage of `engine.io-client`. |
387 |
|
388 |
Make sure `npm install` is run first. |
389 |
|
390 |
## Goals |
391 |
|
392 |
The main goal of `Engine` is ensuring the most reliable realtime communication. |
393 |
Unlike the previous Socket.IO core, it always establishes a long-polling |
394 |
connection first, then tries to upgrade to better transports that are "tested" on |
395 |
the side. |
396 |
|
397 |
During the lifetime of the Socket.IO projects, we've found countless drawbacks |
398 |
to relying on `HTML5 WebSocket` or `Flash Socket` as the first connection |
399 |
mechanisms. |
400 |
|
401 |
Both are clearly the _right way_ of establishing a bidirectional communication, |
402 |
with HTML5 WebSocket being the way of the future. However, to answer most business |
403 |
needs, alternative traditional HTTP 1.1 mechanisms are just as good as delivering |
404 |
the same solution. |
405 |
|
406 |
WebSocket based connections have two fundamental benefits: |
407 |
|
408 |
1. **Better server performance** |
409 |
- _A: Load balancers_<br> |
410 |
Load balancing a long polling connection poses a serious architectural nightmare |
411 |
since requests can come from any number of open sockets by the user agent, but |
412 |
they all need to be routed to the process and computer that owns the `Engine` |
413 |
connection. This negatively impacts RAM and CPU usage. |
414 |
- _B: Network traffic_<br> |
415 |
WebSocket is designed around the premise that each message frame has to be |
416 |
surrounded by the least amount of data. In HTTP 1.1 transports, each message |
417 |
frame is surrounded by HTTP headers and chunked encoding frames. If you try to |
418 |
send the message _"Hello world"_ with xhr-polling, the message ultimately |
419 |
becomes larger than if you were to send it with WebSocket. |
420 |
- _C: Lightweight parser_<br> |
421 |
As an effect of **B**, the server has to do a lot more work to parse the network |
422 |
data and figure out the message when traditional HTTP requests are used |
423 |
(as in long polling). This means that another advantage of WebSocket is |
424 |
less server CPU usage. |
425 |
|
426 |
2. **Better user experience** |
427 |
|
428 |
Due to the reasons stated in point **1**, the most important effect of being able |
429 |
to establish a WebSocket connection is raw data transfer speed, which translates |
430 |
in _some_ cases in better user experience. |
431 |
|
432 |
Applications with heavy realtime interaction (such as games) will benefit greatly, |
433 |
whereas applications like realtime chat (Gmail/Facebook), newsfeeds (Facebook) or |
434 |
timelines (Twitter) will have negligible user experience improvements. |
435 |
|
436 |
Having said this, attempting to establish a WebSocket connection directly so far has |
437 |
proven problematic: |
438 |
|
439 |
1. **Proxies**<br> |
440 |
Many corporate proxies block WebSocket traffic. |
441 |
|
442 |
2. **Personal firewall and antivirus software**<br> |
443 |
As a result of our research, we've found that at least 3 personal security |
444 |
applications block WebSocket traffic. |
445 |
|
446 |
3. **Cloud application platforms**<br> |
447 |
Platforms like Heroku or No.de have had trouble keeping up with the fast-paced |
448 |
nature of the evolution of the WebSocket protocol. Applications therefore end up |
449 |
inevitably using long polling, but the seamless installation experience of |
450 |
Socket.IO we strive for (_"require() it and it just works"_) disappears. |
451 |
|
452 |
Some of these problems have solutions. In the case of proxies and personal programs, |
453 |
however, the solutions many times involve upgrading software. Experience has shown |
454 |
that relying on client software upgrades to deliver a business solution is |
455 |
fruitless: the very existence of this project has to do with a fragmented panorama |
456 |
of user agent distribution, with clients connecting with latest versions of the most |
457 |
modern user agents (Chrome, Firefox and Safari), but others with versions as low as |
458 |
IE 5.5. |
459 |
|
460 |
From the user perspective, an unsuccessful WebSocket connection can translate in |
461 |
up to at least 10 seconds of waiting for the realtime application to begin |
462 |
exchanging data. This **perceptively** hurts user experience. |
463 |
|
464 |
To summarize, **Engine** focuses on reliability and user experience first, marginal |
465 |
potential UX improvements and increased server performance second. `Engine` is the |
466 |
result of all the lessons learned with WebSocket in the wild. |
467 |
|
468 |
## Architecture |
469 |
|
470 |
The main premise of `Engine`, and the core of its existence, is the ability to |
471 |
swap transports on the fly. A connection starts as xhr-polling, but it can |
472 |
switch to WebSocket. |
473 |
|
474 |
The central problem this poses is: how do we switch transports without losing |
475 |
messages? |
476 |
|
477 |
`Engine` only switches from polling to another transport in between polling |
478 |
cycles. Since the server closes the connection after a certain timeout when |
479 |
there's no activity, and the polling transport implementation buffers messages |
480 |
in between connections, this ensures no message loss and optimal performance. |
481 |
|
482 |
Another benefit of this design is that we workaround almost all the limitations |
483 |
of **Flash Socket**, such as slow connection times, increased file size (we can |
484 |
safely lazy load it without hurting user experience), etc. |
485 |
|
486 |
## FAQ |
487 |
|
488 |
### Can I use engine without Socket.IO ? |
489 |
|
490 |
Absolutely. Although the recommended framework for building realtime applications |
491 |
is Socket.IO, since it provides fundamental features for real-world applications |
492 |
such as multiplexing, reconnection support, etc. |
493 |
|
494 |
`Engine` is to Socket.IO what Connect is to Express. An essential piece for building |
495 |
realtime frameworks, but something you _probably_ won't be using for building |
496 |
actual applications. |
497 |
|
498 |
### Does the server serve the client? |
499 |
|
500 |
No. The main reason is that `Engine` is meant to be bundled with frameworks. |
501 |
Socket.IO includes `Engine`, therefore serving two clients is not necessary. If |
502 |
you use Socket.IO, including |
503 |
|
504 |
```html |
505 |
<script src="/socket.io/socket.io.js"> |
506 |
``` |
507 |
|
508 |
has you covered. |
509 |
|
510 |
### Can I implement `Engine` in other languages? |
511 |
|
512 |
Absolutely. The [engine.io-protocol](https://github.com/LearnBoost/engine.io-protocol) |
513 |
repository contains the most up to date description of the specification |
514 |
at all times, and the parser implementation in JavaScript. |
515 |
|
516 |
## License |
517 |
|
518 |
(The MIT License) |
519 |
|
520 |
Copyright (c) 2014 Guillermo Rauch <guillermo@learnboost.com> |
521 |
|
522 |
Permission is hereby granted, free of charge, to any person obtaining |
523 |
a copy of this software and associated documentation files (the |
524 |
'Software'), to deal in the Software without restriction, including |
525 |
without limitation the rights to use, copy, modify, merge, publish, |
526 |
distribute, sublicense, and/or sell copies of the Software, and to |
527 |
permit persons to whom the Software is furnished to do so, subject to |
528 |
the following conditions: |
529 |
|
530 |
The above copyright notice and this permission notice shall be |
531 |
included in all copies or substantial portions of the Software. |
532 |
|
533 |
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, |
534 |
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
535 |
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
536 |
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
537 |
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
538 |
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
539 |
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |