Using Websocket
WebSocket is a network communication protocol that provides the capability for full-duplex communication over a single TCP connection. Unlike the traditional HTTP request-response model, WebSocket allows the server to actively push data to the client, achieving true bidirectional communication.
Key Features:
- Full-duplex communication: The client and server can send and receive data simultaneously.
- Low latency: After the connection is established, the data transmission overhead is minimal.
- Real-time: The server can actively push data without requiring client polling.
- Persistent connection: Maintains the connection state after a single handshake, avoiding repeated connection establishment.
The WebSocket protocol uses URIs starting with ws://
or wss://
(secure connection). It establishes a connection through the standard HTTP handshake process and then upgrades to the WebSocket protocol for communication.
This article describes how to implement Websocket message sending/receiving using Cloud Hosting (container-based and function-based), and how to access these services from the client side.
Using Function Cloud Hosting
Create a directory websocket-demo
locally, create a new index.js
file in the directory, and write the following code:
exports.main = function (event, context) {
console.log({ event, context });
if (context.ws) {
const ws = context.ws;
ws.on("close", (msg) => {
console.log("close: ", msg);
ws.send("bye!");
});
ws.on("message", (msg) => {
console.log("message: ", msg);
ws.send(`echo: ${msg?.data}`);
});
}
};
exports.main.handleUpgrade = async function (upgradeContext) {
console.log(upgradeContext, "upgradeContext");
if (upgradeContext.httpContext.url === "/reject-upgrade") {
return {
allowWebSocket: false,
statusCode: 403,
body: JSON.stringify({ code: "code", message: "message" }),
contentType: "appliaction/json; charset=utf-8",
};
}
return { allowWebSocket: true };
};
This code implements the following functionalities:
- The main function handles message interactions after the WebSocket connection is established:
- Listen for the close event and send a farewell message when the connection is closed.
- Listen for the message event and reply with the current time and message content when a message is received.
- The handleUpgrade function controls the establishment of WebSocket connections:
- When accessing /reject-upgrade, reject the connection.
- Other paths allow the establishment of WebSocket connections.
Deployment and Debugging
It is recommended to use CloudBase CLI for deployment.
After installing the CLI and logging in, navigate to the project root directory and execute the following command:
# Deploying a Function Cloud Hosting Instance
tcb cloudrunfuntion deploy
After the instance is deployed, go to the CloudBase console.
In the left navigation bar, select [CloudBase]. On the [Service List] page, locate the recently deployed instance and click to enter the [Service Details] page. The default domain name can be found on the details page.
Replace the https://
at the beginning of the default domain with ws://
or wss://
, and perform WebSocket connection testing in tools such as Postman.
Using Container Cloud Hosting
You can use the code sample: sample code repository.
After cloning the code repository, navigate to the project root directory. The directory structure is as follows:
├── Dockerfile
├── app
│ └── server.js
└── package.json
Here, app/server.js
is a service implemented using express
and express-ws
, and CloudBase will build the container based on the Dockerfile
.
For more information about Container Cloud Hosting, refer to the Service Development Guide.
Deployment and Debugging
It is recommended to use CloudBase CLI for deployment.
After installing the CLI and logging in, navigate to the project root directory and execute the following command:
# Deploying a Container Cloud Hosting Instance
tcb cloudrun deploy
After the instance is deployed, go to the CloudBase console.
In the left navigation bar, select [CloudBase]. On the [Service List] page, locate the newly deployed instance and click to enter the [Service Details] page. On the details page, find the default domain name. We assume the default domain name for the created service is: https://demo.ap-shanghai.run.tcloudbase.com. Replace the https://
prefix with ws://
or wss://
, for example: wss://demo.ap-shanghai.run.tcloudbase.com, and perform WebSocket connection testing in tools like Postman.
Accessing the websocket Service
WeChat Mini Program
wx.cloud.init({
env: "xxxx-yyy", // Replace with your Environment ID
});
const { socketTask } = await wx.cloud.connectContainer({
service: "websocket-demo", // Replace with your service name
path: "/", // Defaults to the root directory if left blank
});
socketTask.onMessage(function (res) {
console.log("[WEBSOCKET]", res.data);
});
socketTask.onOpen(function (res) {
console.log("[WEBSOCKET]", "Connected successfully!");
socketTask.send({
data: "This is a Mini Program message",
});
});
socketTask.onClose(function (res) {
console.log("[WEBSOCKET] Connection closed!");
});
Updated information can be found in the WeChat Cloud Run documentation.
Browser
const ws = new WebSocket("wss://demo.ap-shanghai.run.tcloudbase.com"); // Replace with your service address
ws.onopen = function () {
console.log("Connection established successfully");
ws.send("WeChat Cloud Run test message"); // Send a message
};
ws.onmessage = function (evt) {
console.log(evt.data);
};
ws.onclose = function () {
console.log("Connection closed");
};
Node.js
In Node.js, you can use the ws module to implement a WebSocket client.
import WebSocket from "ws";
function run() {
const ws = new WebSocket("wss://demo.ap-shanghai.run.tcloudbase.com"); // Replace with your service address
ws.on("close", (code, reason) => {
console.log("close:", code, `${reason}`);
});
ws.on("error", (err) => {
console.error("error: ", err);
});
ws.on("upgrade", () => {
console.log("upgrade");
});
ws.on("ping", () => {
console.log("recv ping message");
});
ws.on("pong", () => {
console.log("recv pong message");
setTimeout(() => {
ws.ping();
}, 1000);
});
ws.on("unexpected-response", (ws, req, res) => {
// Non-upgrade responses and 3xx redirect responses are considered unexpected-response
console.log("recv unexpected-response message");
});
ws.on("message", (data) => {
console.log("received: %s", data);
});
ws.on("open", () => {
ws.ping();
ws.send("string data");
ws.send(Buffer.from("buffer data"));
});
}
run();