root / HServer / 00.Server / 00.Program / node_modules / ws / README.md
이력 | 보기 | 이력해설 | 다운로드 (9.29 KB)
1 | 39 | HKM | # 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 |