The github repository of this article is: https://github.com/weizy0219/nodejs_websocket_examples
Most WebSocket Examples in JavaScript are of nodejs in server side and web brawser in client side, and not that easy to move these client to a nodejs implementation. Besides, as most nodejs WebSocket client are not compatible with native brawser WebSocket client, few examples can work well both in nodejs and web brawser.
This repository contains a list of examples to illustrate the implementation of WebSocket protocal in nodejs, both pure TypeScript or with frameworks like Express or Nestjs.
Each example folder contains independent example, with subfolders to distinguish server and client.
1. Websocket Basics
WebSocket is “To enable web applications to maintain bidirectional communications with server-side processes”, there are official implementation and unofficial ones.
The top three popular websocket libraries on npmjs are ws、socket.io、and websocket( There are also other implementations like WebSocket-Nodeor µWebSockets). We use both ws and socket.io in this repository because they each has there advantages and disadvantages.
The ws library is the most popular one and it is fully compatible with the Official WebSocket protocal, however, if you want to use ws as client in nodejs, a wrapper like isomorphic-ws is necessary, which is also used in the examples.
The socket.io library has its own features like load balance and auto-reconnection functions although it is not compatible with the Official WebSocket protocal and you need to install it both in server side and client side. In client side, you need socket.io-client library instead of socket.io.
2. Basic Example Functions
The examples are used to illustrate implementations of websocket, thus no complex functions will not be apllied here. The basic functions of each example contains following functions (unless the library has no relative function),and some of the example code are from original library examples:
- A websocket server in pure nodejs or with a http framework
- Two websocket client in brawser and in nodejs (with or without framework)
- Start both server and client side(open the html file in a web brawser for the brawser client), the client will try to connect to the server
- When the client connect to the Server, the server send an
messageevent withhello clientto the client - When the client receives the
messageevent, it send anresponseevent withresponse + randmon numberto the server - When the Server receives the
responseevent, it send anendevent with the content it received. - When the Client receives the
endevent, it closes the connection after 3s delay. - Both server and client print every event content it received in the console.
- Both server and client print the connect and disconnect status change in the console.
- Both server and client print error messages in the console.
3. Examples
3.1 nodejs ws example
This example contains WebSocket server and client example implemented with nodejs. The server folder contains a normal server ,install and run npm run start to start it. There is another ws server wrapped in a httpServer in the server folder named server2.ts, run npm run start2 to start it, to make the example simple, the two servers run on the same port 18000(the http server listens port 3000).
client folder contains:
- A pure brawser client
client.html, open with a brawser to start - A
wsclient with native ws library, runnpm run start - A
wsclient compatible with native WebSocket protocol, runnpm run start2
Note:
The function format are different from ws and native WebSocket, in ws library:
ws.on('message', (message)=>{console.log('received: %s', message);});
In native WebSocket compatible format:
ws.onmessage=(message)=>{console.log('received: %s', message);}
Besides, the message in the two protocols are also different, in the ws library it is WebSocket.data while in the native WebSocket protocol is WebSocket.MessageEvent, the latter structure is similar as below as the former contains only the data part.
MessageEvent {target: [WebSocket],type: 'message',data: '{"event":"end","data":"response: 0.3416359669492526"}'}
3.2 nodejs socketio example
This example contains socket.io server and client implemented with nodejs. Install and npm run start in server and client folder to start each. There is another socket.io server wrapped in a httpServer in the server folder named server2.ts, run npm run start2 to start it, to make the example simple, the two servers run on the same port 18000
There is also a index.html file which implemented a brawser client:
- As socket.io is not compatible with native WebSocket, there is a
socket.io.jsfile (asocket.io.js.mapmay also needed, both files can be found onsocket.iolibraryclient-distfolder) which is replied by the html file. - Using the obsolete
socket.io.js v2file to connectv3server may cause400 error. - As
socket.io v3usesCORS, simply open theindex.htmlfile in a brawser cannot visit the server. We installedhttp-serverhere (which uses index.html as default page), and config theCORSoption in the server (see below), runnpm run startweband visithttp://localhost:8081in a brawser to connect to the server.
NOTICE:
This repository uses socket.io v3 and not compatible with socket.io. See Socket.io Document for the detailed differences between the two version. Some import feature are as follows:
- As
socket.io v3is rewritten byTypeScript, there is no need to import@types/socket.ioor@types/socket.io-clientlibrary to usesocket.ioinTypeSctipt, import the above libraries in your code may cause mistake. CORSneeds to be explicitly announced as follows:
const io = require("socket.io")(httpServer, {cors: {origin: "https://example.com",methods: ["GET", "POST"]}});
socket.iosupport autoreconnection mechanism which is enabled by default, if you want to test the function, just comment thesetTimeoutfunction in client, stop and start the server again, the client will reconnect to the server automatically.socket.iosupport message acknowledgement mechanism, theresponseevent in this example added it, the server will give an acknowledgement message through callback function when it receives a response message.- The content of
socket.ioevent are highly customised ,you need to decide and encode/decode the content and avoid possible mistakes.
3.3 nestjs ws example
This example contains both WebSocket server and client implementation with popular Nestjs framework using ws library. As Nestjs is a server framework itself, a html file is added with nestjs serve Static function and MVC service. the communication interfaces in this example is similar to 1. nodejs ws example, so the servers and clients can connect with each other. However, for test purpose, the functions a modifed in this example so as to keep the client keep connected with the server until there is an order to terminate:
- The server will not send an
endmessage when it received aresponsemessage, instead, it sends a sameresponsemessage to the client. - A
responsemessage listener is added to the client, it will print the message it received. - A
terminatemessage will be send from the client trigged by a http requestsendTerminate, the server will send the oldendmessage when it received theterminatemessage.
The client httpServer works on port 3001, two apis were added to update data and terminate connection
-Get http://localhost:3001/ws-client/getdata to send response and update the data it received.
-Get http://localhost:3001/ws-client/sendTerminate 用to send terminatemessage,This will also terminate the client app, you need restart it again
A client.http file is created in client folder to test http requests, which can be used by vscode plugin REST Client.
no cors configuration when use ws library.
To Use:
- In the
serverandclientrunnpm run startto start them and see the result. - In a brawser visit
http://localhost:3001, to see and update data in console and in the page. - To work with
1. nodejs ws exampleservers and clients, you need to pay attention to the API difference.
3.4 nestjs socket io example
This example contains both WebSocket server and client implementation with popular Nestjs framework using socketio library. The program structure and API interface are exactly the same as example 3. Except for some important NOTES:
- As
socket.ioversion 3.x and 2.x are incompatible, they cannot work together, which means the server and client shall of the same major version. Nestjsbuilt-insocket.iolibrary@nestjs/platform-iowas written with socket.io version 2, so it is incampatible with a version 3 client.- The
Nestjsauthor promised to updatesocket-ioon nestjs 8 ,however, if you want to usesocket.io v3in nestjs, a temporary approach is introduced in nestjs issue 5676, use thesocket-io.adapterin the issue (thenameline under cookie shall be removed) instead of the official one. This is the way we used here. - You may also downgrade the client version to v2.x ,however, we did not try that way here.
- SO FAR, the server and client works well in this example, but if you want the server in this example works together with the client in example 2, there is still a problem, perhaps due to the
@WebSocketGateway()decorator mechanism, you will not visit the server if theportparameter (for example@WebSocketGateway(18000)) is different from the server http port (for example app.listen(3000)) even if cors is enabled. You shold leave the@WebSocketGateway()decorator blank and use the client to visit the same http port.
