root / HServer / 00.Server / 00.Program / node_modules / ws / README.md
이력 | 보기 | 이력해설 | 다운로드 (9.29 KB)
1 |
# ws: a Node.js WebSocket library |
---|---|
2 |
|
3 |
[](https://www.npmjs.com/package/ws) |
4 |
[](https://travis-ci.org/websockets/ws) |
5 |
[](https://ci.appveyor.com/project/lpinca/ws) |
6 |
[](https://coveralls.io/r/websockets/ws?branch=master) |
7 |
|
8 |
ws is a simple to use, blazing fast, and thoroughly tested WebSocket client |
9 |
and server implementation. |
10 |
|
11 |
Passes the quite extensive Autobahn test suite: [server][server-report], |
12 |
[client][client-report]. |
13 |
|
14 |
**Note**: This module does not work in the browser. The client in the docs is a |
15 |
reference to a back end with the role of a client in the WebSocket |
16 |
communication. Browser clients must use the native |
17 |
[`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) object. |
18 |
|
19 |
## Table of Contents |
20 |
|
21 |
* [Protocol support](#protocol-support) |
22 |
* [Installing](#installing) |
23 |
+ [Opt-in for performance and spec compliance](#opt-in-for-performance-and-spec-compliance) |
24 |
* [API docs](#api-docs) |
25 |
* [WebSocket compression](#websocket-compression) |
26 |
* [Usage examples](#usage-examples) |
27 |
+ [Sending and receiving text data](#sending-and-receiving-text-data) |
28 |
+ [Sending binary data](#sending-binary-data) |
29 |
+ [Server example](#server-example) |
30 |
+ [Broadcast example](#broadcast-example) |
31 |
+ [ExpressJS example](#expressjs-example) |
32 |
+ [echo.websocket.org demo](#echowebsocketorg-demo) |
33 |
+ [Other examples](#other-examples) |
34 |
* [Error handling best practices](#error-handling-best-practices) |
35 |
* [FAQ](#faq) |
36 |
+ [How to get the IP address of the client?](#how-to-get-the-ip-address-of-the-client) |
37 |
+ [How to detect and close broken connections?](#how-to-detect-and-close-broken-connections) |
38 |
+ [How to connect via a proxy?](#how-to-connect-via-a-proxy) |
39 |
* [Changelog](#changelog) |
40 |
* [License](#license) |
41 |
|
42 |
## Protocol support |
43 |
|
44 |
* **HyBi drafts 07-12** (Use the option `protocolVersion: 8`) |
45 |
* **HyBi drafts 13-17** (Current default, alternatively option `protocolVersion: 13`) |
46 |
|
47 |
## Installing |
48 |
|
49 |
``` |
50 |
npm install --save ws |
51 |
``` |
52 |
|
53 |
### Opt-in for performance and spec compliance |
54 |
|
55 |
There are 2 optional modules that can be installed along side with the ws |
56 |
module. These modules are binary addons which improve certain operations. |
57 |
Prebuilt binaries are available for the most popular platforms so you don't |
58 |
necessarily need to have a C++ compiler installed on your machine. |
59 |
|
60 |
- `npm install --save-optional bufferutil`: Allows to efficiently perform |
61 |
operations such as masking and unmasking the data payload of the WebSocket |
62 |
frames. |
63 |
- `npm install --save-optional utf-8-validate`: Allows to efficiently check |
64 |
if a message contains valid UTF-8 as required by the spec. |
65 |
|
66 |
## API docs |
67 |
|
68 |
See [`/doc/ws.md`](./doc/ws.md) for Node.js-like docs for the ws classes. |
69 |
|
70 |
## WebSocket compression |
71 |
|
72 |
ws supports the [permessage-deflate extension][permessage-deflate] which |
73 |
enables the client and server to negotiate a compression algorithm and its |
74 |
parameters, and then selectively apply it to the data payloads of each |
75 |
WebSocket message. |
76 |
|
77 |
The extension is disabled by default on the server and enabled by default on |
78 |
the client. It adds a significant overhead in terms of performance and memory |
79 |
consumption so we suggest to enable it only if it is really needed. |
80 |
|
81 |
The client will only use the extension if it is supported and enabled on the |
82 |
server. To always disable the extension on the client set the |
83 |
`perMessageDeflate` option to `false`. |
84 |
|
85 |
```js |
86 |
const WebSocket = require('ws'); |
87 |
|
88 |
const ws = new WebSocket('ws://www.host.com/path', { |
89 |
perMessageDeflate: false |
90 |
}); |
91 |
``` |
92 |
|
93 |
## Usage examples |
94 |
|
95 |
### Sending and receiving text data |
96 |
|
97 |
```js |
98 |
const WebSocket = require('ws'); |
99 |
|
100 |
const ws = new WebSocket('ws://www.host.com/path'); |
101 |
|
102 |
ws.on('open', function open() { |
103 |
ws.send('something'); |
104 |
}); |
105 |
|
106 |
ws.on('message', function incoming(data) { |
107 |
console.log(data); |
108 |
}); |
109 |
``` |
110 |
|
111 |
### Sending binary data |
112 |
|
113 |
```js |
114 |
const WebSocket = require('ws'); |
115 |
|
116 |
const ws = new WebSocket('ws://www.host.com/path'); |
117 |
|
118 |
ws.on('open', function open() { |
119 |
const array = new Float32Array(5); |
120 |
|
121 |
for (var i = 0; i < array.length; ++i) { |
122 |
array[i] = i / 2; |
123 |
} |
124 |
|
125 |
ws.send(array); |
126 |
}); |
127 |
``` |
128 |
|
129 |
### Server example |
130 |
|
131 |
```js |
132 |
const WebSocket = require('ws'); |
133 |
|
134 |
const wss = new WebSocket.Server({ port: 8080 }); |
135 |
|
136 |
wss.on('connection', function connection(ws) { |
137 |
ws.on('message', function incoming(message) { |
138 |
console.log('received: %s', message); |
139 |
}); |
140 |
|
141 |
ws.send('something'); |
142 |
}); |
143 |
``` |
144 |
|
145 |
### Broadcast example |
146 |
|
147 |
```js |
148 |
const WebSocket = require('ws'); |
149 |
|
150 |
const wss = new WebSocket.Server({ port: 8080 }); |
151 |
|
152 |
// Broadcast to all. |
153 |
wss.broadcast = function broadcast(data) { |
154 |
wss.clients.forEach(function each(client) { |
155 |
if (client.readyState === WebSocket.OPEN) { |
156 |
client.send(data); |
157 |
} |
158 |
}); |
159 |
}; |
160 |
|
161 |
wss.on('connection', function connection(ws) { |
162 |
ws.on('message', function incoming(data) { |
163 |
// Broadcast to everyone else. |
164 |
wss.clients.forEach(function each(client) { |
165 |
if (client !== ws && client.readyState === WebSocket.OPEN) { |
166 |
client.send(data); |
167 |
} |
168 |
}); |
169 |
}); |
170 |
}); |
171 |
``` |
172 |
|
173 |
### ExpressJS example |
174 |
|
175 |
```js |
176 |
const express = require('express'); |
177 |
const http = require('http'); |
178 |
const url = require('url'); |
179 |
const WebSocket = require('ws'); |
180 |
|
181 |
const app = express(); |
182 |
|
183 |
app.use(function (req, res) { |
184 |
res.send({ msg: "hello" }); |
185 |
}); |
186 |
|
187 |
const server = http.createServer(app); |
188 |
const wss = new WebSocket.Server({ server }); |
189 |
|
190 |
wss.on('connection', function connection(ws, req) { |
191 |
const location = url.parse(req.url, true); |
192 |
// You might use location.query.access_token to authenticate or share sessions |
193 |
// or req.headers.cookie (see http://stackoverflow.com/a/16395220/151312) |
194 |
|
195 |
ws.on('message', function incoming(message) { |
196 |
console.log('received: %s', message); |
197 |
}); |
198 |
|
199 |
ws.send('something'); |
200 |
}); |
201 |
|
202 |
server.listen(8080, function listening() { |
203 |
console.log('Listening on %d', server.address().port); |
204 |
}); |
205 |
``` |
206 |
|
207 |
### echo.websocket.org demo |
208 |
|
209 |
```js |
210 |
const WebSocket = require('ws'); |
211 |
|
212 |
const ws = new WebSocket('wss://echo.websocket.org/', { |
213 |
origin: 'https://websocket.org' |
214 |
}); |
215 |
|
216 |
ws.on('open', function open() { |
217 |
console.log('connected'); |
218 |
ws.send(Date.now()); |
219 |
}); |
220 |
|
221 |
ws.on('close', function close() { |
222 |
console.log('disconnected'); |
223 |
}); |
224 |
|
225 |
ws.on('message', function incoming(data) { |
226 |
console.log(`Roundtrip time: ${Date.now() - data} ms`); |
227 |
|
228 |
setTimeout(function timeout() { |
229 |
ws.send(Date.now()); |
230 |
}, 500); |
231 |
}); |
232 |
``` |
233 |
|
234 |
### Other examples |
235 |
|
236 |
For a full example with a browser client communicating with a ws server, see the |
237 |
examples folder. |
238 |
|
239 |
Otherwise, see the test cases. |
240 |
|
241 |
## Error handling best practices |
242 |
|
243 |
```js |
244 |
// If the WebSocket is closed before the following send is attempted |
245 |
ws.send('something'); |
246 |
|
247 |
// Errors (both immediate and async write errors) can be detected in an optional |
248 |
// callback. The callback is also the only way of being notified that data has |
249 |
// actually been sent. |
250 |
ws.send('something', function ack(error) { |
251 |
// If error is not defined, the send has been completed, otherwise the error |
252 |
// object will indicate what failed. |
253 |
}); |
254 |
|
255 |
// Immediate errors can also be handled with `try...catch`, but **note** that |
256 |
// since sends are inherently asynchronous, socket write failures will *not* be |
257 |
// captured when this technique is used. |
258 |
try { ws.send('something'); } |
259 |
catch (e) { /* handle error */ } |
260 |
``` |
261 |
|
262 |
## FAQ |
263 |
|
264 |
### How to get the IP address of the client? |
265 |
|
266 |
The remote IP address can be obtained from the raw socket. |
267 |
|
268 |
```js |
269 |
const WebSocket = require('ws'); |
270 |
|
271 |
const wss = new WebSocket.Server({ port: 8080 }); |
272 |
|
273 |
wss.on('connection', function connection(ws, req) { |
274 |
const ip = req.connection.remoteAddress; |
275 |
}); |
276 |
``` |
277 |
|
278 |
When the server runs behind a proxy like NGINX, the de-facto standard is to use |
279 |
the `X-Forwarded-For` header. |
280 |
|
281 |
```js |
282 |
wss.on('connection', function connection(ws, req) { |
283 |
const ip = req.headers['x-forwarded-for']; |
284 |
}); |
285 |
``` |
286 |
|
287 |
### How to detect and close broken connections? |
288 |
|
289 |
Sometimes the link between the server and the client can be interrupted in a |
290 |
way that keeps both the server and the client unaware of the broken state of the |
291 |
connection (e.g. when pulling the cord). |
292 |
|
293 |
In these cases ping messages can be used as a means to verify that the remote |
294 |
endpoint is still responsive. |
295 |
|
296 |
```js |
297 |
const WebSocket = require('ws'); |
298 |
|
299 |
const wss = new WebSocket.Server({ port: 8080 }); |
300 |
|
301 |
function heartbeat() { |
302 |
this.isAlive = true; |
303 |
} |
304 |
|
305 |
wss.on('connection', function connection(ws) { |
306 |
ws.isAlive = true; |
307 |
ws.on('pong', heartbeat); |
308 |
}); |
309 |
|
310 |
const interval = setInterval(function ping() { |
311 |
wss.clients.forEach(function each(ws) { |
312 |
if (ws.isAlive === false) return ws.terminate(); |
313 |
|
314 |
ws.isAlive = false; |
315 |
ws.ping('', false, true); |
316 |
}); |
317 |
}, 30000); |
318 |
``` |
319 |
|
320 |
Pong messages are automatically sent in response to ping messages as required |
321 |
by the spec. |
322 |
|
323 |
### How to connect via a proxy? |
324 |
|
325 |
Use a custom `http.Agent` implementation like [https-proxy-agent][] or |
326 |
[socks-proxy-agent][]. |
327 |
|
328 |
## Changelog |
329 |
|
330 |
We're using the GitHub [releases][changelog] for changelog entries. |
331 |
|
332 |
## License |
333 |
|
334 |
[MIT](LICENSE) |
335 |
|
336 |
[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent |
337 |
[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent |
338 |
[client-report]: http://websockets.github.io/ws/autobahn/clients/ |
339 |
[server-report]: http://websockets.github.io/ws/autobahn/servers/ |
340 |
[permessage-deflate]: https://tools.ietf.org/html/rfc7692 |
341 |
[changelog]: https://github.com/websockets/ws/releases |