socketio
socket.io说明
Socket.io是一个WebSocket库,包括了客户端的js和服务器端的nodejs,它的目标是构建可以在不同浏览器和移动设备上使用的实时应用。
它会自动根据浏览器从WebSocket、AJAX长轮询、Iframe流等等各种方式中选择最佳的方式来实现网络实时应用,非常方便和人性化,而且支持的浏览器最低达IE5.5
socket.io特点
实时分析:将数据推送到客户端,这些客户端会被表示为实时计数器,图表或日志客户。
实时通信和聊天:只需几行代码便可写成一个Socket.IO的”Hello,World”聊天应用。
二进制流传输:从1.0版本开始,Socket.IO支持任何形式的二进制文件传输,例如:图片,视频,音频等。
文档合并:允许多个用户同时编辑一个文档,并且能够看到每个用户做出的修改。
socketio 使用
服务端
- 配置jiangHuConfig, 启用socket
// config.default.jsjiangHuConfig: {enableSocket: true}
- 配置socketIO配置信息
// config.default.js jianghuConfig同级socketIO: {path: `/${appId}/socket.io`,serveClient: true,connectTimeout: 45000,// 多work模式下需要 启用 redis adapter// redis: {// host: "127.0.0.1",// port: "6379",// // password: '',// db: 0,// },},
- 发送socket消息
const { socketIO } = this.app;socketIO.to(toSocketId).emit(resourcePath, socketBody);
客户端
- 初始化socket 客户端
function init() {const requestBody = {packageId,packageType: "socketRequest",deviceId: socket.deviceId,status: null,timestamp: new Date().toISOString(),appData: {appId: window.appInfo.appId,pageId: "socket",actionId: "connect",authToken: socket.authToken,actionData: {socketId,},},};try {socket.client = io("/", {path: `/${window.appInfo.appId}/socket.io`,auth: requestBody,closeOnBeforeunload: true,transports: ["websocket"],forceNew: true,timeout: 5000,secure: false, // 是否支持SSL/TLS});} catch (e) {console.error(e);}}
- 注册客户端监听事件
socket.client.on("resource", async (message) => {console.log("==== [socket channel.resource]", JSON.stringify(message));const { appId, pageId, actionId } = message.appData;socket.packageId = message.packageId;// 认证成功if (pageId === "socket" && actionId === "connect") {// 每次掉线都会重新走一遍认证过程,code=100的逻辑要注意别搞混// 设置在线标识socket.online = true;socket.loadFinish = true;console.log("socket.hasDisconnectOrError :: " + socket.hasDisconnectOrError)socket.onReConnect(socket.hasDisconnectOrError)} else {socket.receiveSocketMsg(message.appData, message.packageId);if (socket.packageListeners[message.packageId]) {const { callback } = socket.packageListeners[message.packageId];callback(message);}}});socket.client.on("connect", (message) => {console.log("==== [socket channel.onConnect]", message);});socket.client.on("connect_timeout", (message) => {console.log("==== [socket channel.connect_timeout]", message);});socket.client.on("connect_error", (message) => {console.log("==== [socket channel.onError]", message);socket.hasDisconnectOrError = true;socket.online = false;});socket.client.on("disconnect", (message) => {console.log("==== [socket channel.disconnect]", message);socket.online = false;socket.hasDisconnectOrError = true;});socket.client.on("reconnect", (message) => {socket.hasDisconnectOrError = true;console.log("==== [socket channel.onReconnect]", message);});socket.client.on("reconnect_attempt", (message) => {console.log("==== [socket channel.onReconnectAttempt]", message);});socket.client.on("reconnect_failed", (message) => {console.log("==== [socket channel.onReconnectFailed]", message);});socket.client.on("reconnect_error", (message) => {console.log("==== [socket channel.onReconnectError]", message);});socket.client.on("ping", (message) => {// 心跳请求// callback_onIMPingconsole.log("==== [socket channel.onPing]", message);});socket.client.on("pong", (message) => {// 心跳响应// callback_onIMPongconsole.log("==== [socket channel.onPong]", message);});
- 添加socket客户端断开重连逻辑
// 每5s检查一下连接状态,若连接已断开,则尝试重新连接setInterval(() => {if (!socket.connected) {this.init()}}, 5000)
- 发送socket消息
const packageId = `${Date.now()}_${_.random(1000000, 9999999)}`;const requestBody = {packageId,packageType: "socketForward",deviceId: socket.deviceId,status: null,timestamp: new Date().toISOString(),appData: {appId: window.appInfo.appId,pageId: "socket",actionId,authToken: socket.authToken,actionData,},};socket.client.emit("resource", requestBody);