Websocket
Native WebSocket
WS - A NodeJS WebSocket library
WS is a WebSocket server for NodeJS. It's quite a low level: you listen to incoming connection requests and respond to raw messages as either strings or byte buffers. So you can consider it as a Native WebSocket in NodeJS world. Below are some examples of how you can create a WebSocket Server using WS
To install WS you can run the following command
npm install ws
Simple Server
import { WebSocketServer } from 'ws'
// Automatically create http server at port 8080
const wss = new WebSocketServer({ port: 8080 })
// listen for client connections
wss.on('connection', function connection(ws) {
// listen for client sending messages
ws.on('message', function message(data) {
console.log('received: %s', data)
})
// send messages to client
ws.send('something')
})
External HTTP Server
In case you want to use your own http server
import { createServer } from 'http'
import { WebSocketServer } from 'ws'
const server = createServer()
// Pass in the external server instance
const wss = new WebSocketServer({ server })
wss.on('connection', function connection(ws) {
ws.on('message', function message(data) {
console.log('received: %s', data)
})
ws.send('something')
})
server.listen(8080)
Multiple servers
This is a more complicated case when you want to have multiple WebSocket Servers sharing a single HTTP server for different purposes. In this case, you will need to handle upgrade requests on your own, but thankfully, WS also has a built-in handleUpgrade
method so you just need to pass in the parameters.
import { createServer } from 'http'
import { parse } from 'url'
import { WebSocketServer } from 'ws'
const server = createServer()
// Remember to set noServer option to true
const wss1 = new WebSocketServer({ noServer: true })
const wss2 = new WebSocketServer({ noServer: true })
wss1.on('connection', function connection(ws) {
// ...
})
wss2.on('connection', function connection(ws) {
// ...
})
// Listern for upgrade requests from clients
server.on('upgrade', function upgrade(request, socket, head) {
const { pathname } = parse(request.url)
// Using built-in handleUpgrade method
if (pathname === '/foo') {
wss1.handleUpgrade(request, socket, head, function done(ws) {
wss1.emit('connection', ws, request)
})
} else if (pathname === '/bar') {
wss2.handleUpgrade(request, socket, head, function done(ws) {
wss2.emit('connection', ws, request)
})
} else {
socket.destroy()
}
})
server.listen(8080)
WebSocket API
Modern browsers nowadays are all supported WebSocket API, so Front-end developers can integrate WebSocket into their applications without having to install any third-party libraries.
To create a WebSocket
instance use the WebSocket() constructor.
WebSocket
instance has 4 events that you should listen to:
- open: triggered when the connection between the client and the server established
- message: triggered when the WebSocket receives messages sent by the server
- close: triggered when the connection is closed either by the client or the server
- error: triggered when there are some errors
WebSocket
also has 2 methods that you need to know:
close()
: to close the connectionsend()
: to send the message to the server
See the below example for how to use WebSocket API in React
// Server Code/*const wss = new WebSocketServer({ noServer: true })wss.on('connection', function connection(ws) {ws.on('message', (data) => {const stringData = data.toString()if (stringData === 'Hi') {ws.send('Hello')}})})*/function WebSocketClient() {const [messages, setMessages] = useState([])const handleConnect = () => {let connection = nullif (!('WebSocket' in window)) {console.warn('WebSocket is not available on this browser')}connection = new WebSocket(`${WebSocketURI}/ws`)connection.addEventListener('message', ({ data }) => {setTimeout(() => {try {setMessages((m) => [...m, `Received: ${data}`])connection.close()} catch (error) {console.log(error.message)}}, 1000)})connection.addEventListener('open', () => {setMessages((m) => [...m, 'Connection established'])setTimeout(() => {connection.send('Hi')setMessages((m) => [...m, 'Sent: Hi'])}, 1000)})connection.addEventListener('close', () => {setMessages((m) => [...m, 'Connection closed'])})connection.addEventListener('error', (err) => {setMessages((m) => [...m, `Error: ${err.message}`])})}return (<div><Button onClick={handleConnect}>Connect</Button><div>{messages.map((m) => (<div key={m}>{m}</div>))}</div></div>)}