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
  1. // config.default.js
  2. jiangHuConfig: {
  3. enableSocket: true
  4. }
  • 配置socketIO配置信息
    1. // config.default.js jianghuConfig同级
    2. socketIO: {
    3. path: `/${appId}/socket.io`,
    4. serveClient: true,
    5. connectTimeout: 45000,
    6. // 多work模式下需要 启用 redis adapter
    7. // redis: {
    8. // host: "127.0.0.1",
    9. // port: "6379",
    10. // // password: '',
    11. // db: 0,
    12. // },
    13. },
  • 发送socket消息
    1. const { socketIO } = this.app;
    2. socketIO.to(toSocketId).emit(resourcePath, socketBody);

客户端

  • 初始化socket 客户端
  1. function init() {
  2. const requestBody = {
  3. packageId,
  4. packageType: "socketRequest",
  5. deviceId: socket.deviceId,
  6. status: null,
  7. timestamp: new Date().toISOString(),
  8. appData: {
  9. appId: window.appInfo.appId,
  10. pageId: "socket",
  11. actionId: "connect",
  12. authToken: socket.authToken,
  13. actionData: {
  14. socketId,
  15. },
  16. },
  17. };
  18. try {
  19. socket.client = io("/", {
  20. path: `/${window.appInfo.appId}/socket.io`,
  21. auth: requestBody,
  22. closeOnBeforeunload: true,
  23. transports: ["websocket"],
  24. forceNew: true,
  25. timeout: 5000,
  26. secure: false, // 是否支持SSL/TLS
  27. });
  28. } catch (e) {
  29. console.error(e);
  30. }
  31. }
  • 注册客户端监听事件
    1. socket.client.on("resource", async (message) => {
    2. console.log("==== [socket channel.resource]", JSON.stringify(message));
    3. const { appId, pageId, actionId } = message.appData;
    4. socket.packageId = message.packageId;
    5. // 认证成功
    6. if (pageId === "socket" && actionId === "connect") {
    7. // 每次掉线都会重新走一遍认证过程,code=100的逻辑要注意别搞混
    8. // 设置在线标识
    9. socket.online = true;
    10. socket.loadFinish = true;
    11. console.log("socket.hasDisconnectOrError :: " + socket.hasDisconnectOrError)
    12. socket.onReConnect(socket.hasDisconnectOrError)
    13. } else {
    14. socket.receiveSocketMsg(message.appData, message.packageId);
    15. if (socket.packageListeners[message.packageId]) {
    16. const { callback } = socket.packageListeners[message.packageId];
    17. callback(message);
    18. }
    19. }
    20. });
    21. socket.client.on("connect", (message) => {
    22. console.log("==== [socket channel.onConnect]", message);
    23. });
    24. socket.client.on("connect_timeout", (message) => {
    25. console.log("==== [socket channel.connect_timeout]", message);
    26. });
    27. socket.client.on("connect_error", (message) => {
    28. console.log("==== [socket channel.onError]", message);
    29. socket.hasDisconnectOrError = true;
    30. socket.online = false;
    31. });
    32. socket.client.on("disconnect", (message) => {
    33. console.log("==== [socket channel.disconnect]", message);
    34. socket.online = false;
    35. socket.hasDisconnectOrError = true;
    36. });
    37. socket.client.on("reconnect", (message) => {
    38. socket.hasDisconnectOrError = true;
    39. console.log("==== [socket channel.onReconnect]", message);
    40. });
    41. socket.client.on("reconnect_attempt", (message) => {
    42. console.log("==== [socket channel.onReconnectAttempt]", message);
    43. });
    44. socket.client.on("reconnect_failed", (message) => {
    45. console.log("==== [socket channel.onReconnectFailed]", message);
    46. });
    47. socket.client.on("reconnect_error", (message) => {
    48. console.log("==== [socket channel.onReconnectError]", message);
    49. });
    50. socket.client.on("ping", (message) => {
    51. // 心跳请求
    52. // callback_onIMPing
    53. console.log("==== [socket channel.onPing]", message);
    54. });
    55. socket.client.on("pong", (message) => {
    56. // 心跳响应
    57. // callback_onIMPong
    58. console.log("==== [socket channel.onPong]", message);
    59. });
  • 添加socket客户端断开重连逻辑
  1. // 每5s检查一下连接状态,若连接已断开,则尝试重新连接
  2. setInterval(() => {
  3. if (!socket.connected) {
  4. this.init()
  5. }
  6. }, 5000)
  • 发送socket消息
  1. const packageId = `${Date.now()}_${_.random(1000000, 9999999)}`;
  2. const requestBody = {
  3. packageId,
  4. packageType: "socketForward",
  5. deviceId: socket.deviceId,
  6. status: null,
  7. timestamp: new Date().toISOString(),
  8. appData: {
  9. appId: window.appInfo.appId,
  10. pageId: "socket",
  11. actionId,
  12. authToken: socket.authToken,
  13. actionData,
  14. },
  15. };
  16. socket.client.emit("resource", requestBody);