• 0
  • 新人请关照

关于node请求在socket通讯中的处理

先上个图
image.png
如图,前端请求后,后端node通过socket到客户端获取数据在返回到服务端。
列子: 1.前端get请求:/index
2.node express 设置路由 router.get(/index, (req, res) => { … 到这里需要通过socket到客户端获取数据, socket.write(XXX) })
问题:
1.当客户端通过socket返回数据到服务端时,如何把数据返回到前台。正常的返回到前端的操作如res.json(xxx)等。但当客户端通过socket传输数据时是在socket.on(‘data’, function (data)这个事件中接收,此时的上下文环境并无res对象。如吧res存在全局可res.json(xxx)返回。
2.多个socket客户端如何管理。存在一个全局集合?可能会有内存泄露的风险。
水平有限,表达的可能有问题。不知道老哥们是否明白。小弟再此磕头了,砰砰砰砰!!!望指导

阅读 250
评论
    2 个回答
    • 618

    socket 的目标, 称为服务端, 更加好理解一些吧...
    按照我的理解, 应该是, 每一个请求 /index, 都通过一个函数, 返回一个Promise, 其中新建一个socket连接, 然后写入数据, 等接收完了 resolve.
    如果你是保持一个长连接, 那就需要自己维护一个 socket 池吧. 但是感觉没啥必要...

      你要的不是某种形式的RPC么,找个现成的实现就好了。
      再者从你的描述中看不需要多个socket客户端啊

      你的图和你的描述貌似对不上,终端请求你的http server, http server与另外的socket server通信对吗
      那么你的http server中只要有一个 socket client就行了。如果要区分终端可以通信的时候带上session id嘛

      PS:抱歉我没看仔细,你的情况是 web 与 socket 两个终端对吧,如果是这样你有一个关键的逻辑没讲,web请求过来后是与哪一个socket client 通信,还是所有的


      写个小demo供参考,思路就是把tcp通信也像http一样配对起来:

      // Connection.js
      const { EventEmitter } = require("events");
      class Message {
        constructor(id, value) {
          this.id = id;
          this.value = value;
        }
        encode() {
          return `${this.id}:${this.value}\n`;
        }
        static decode(str) {
          const arr = str.split(":");
          return new Message(Number(arr[0]), arr[1]);
        }
      }
      
      class Connection extends EventEmitter {
        static uid = 0;
        received = Buffer.alloc(1024);
        size = 0;
        constructor(socket) {
          super();
          this.socket = socket;
          this.id = Connection.uid++;
          socket.on("data", this.onReceive.bind(this));
          socket.on("close", this.onClose.bind(this));
          socket.on("error", this.onClose.bind(this));
        }
        onReceive(data) {
          const chr10 = 10;
          for (let i = 0, len = data.byteLength; i < len; i++) {
            this.received[this.size++] = data[i];
            if (data[i] === chr10) {
              const message = this.received.toString("utf-8", 0, this.size - 1);
              this.handle(message);
              this.size = 0;
            }
          }
        }
        onClose() {
          this.socket.removeAllListeners();
          this.closed = true;
        }
        handle(str) {
          const message = Message.decode(str);
          this.emit("message", message);
        }
        flush(data) {
          if (this.closed) return;
          this.socket.write(data);
        }
      }
      
      module.exports = {
        Message,
        Connection,
      };
      // server.js
      const express = require("express");
      const { createServer } = require("net");
      const { Message, Connection } = require("./Connection");
      const clients = [];
      function getClient(req) {
        // matching client
        if (clients.length > 0) return clients[0];
      }
      const app = express();
      app.get("/", (req, res) => {
        const client = getClient(req);
        if (client) {
          remoteCall(client, "hello")
            .then((message) => res.send(message))
            .catch((e) => res.send(e));
        } else {
          res.send("client not found");
        }
      });
      app.listen(3000);
      
      const socketServer = createServer();
      socketServer.on("connection", (socket) => {
        clients.push(new Connection(socket));
      });
      socketServer.listen(5052);
      
      let uid = 0;
      function remoteCall(client, value, timeout = 1000) {
        let onMessage = null;
        let abort = false;
        return Promise.race([
          new Promise((resolve, reject) => {
            let id = ++uid;
            onMessage = (msg) => {
              client.off("message", onMessage);
              if (abort) return;
              if (msg.id == id) {
                resolve(msg);
              }
            };
            client.on("message", onMessage);
            const message = new Message(id, value);
            client.flush(message.encode());
          }),
          new Promise((_, reject) => {
            setTimeout(() => {
              abort = true;
              reject({ timeout });
            }, timeout);
          }),
        ]);
      }
      
      setInterval(() => {
        for (let i = clients.length - 1; i > -1; i--) {
          if (clients[i].closed) {
            clients.splice(i, 1);
          }
        }
      }, 1000);
      // client.js
      const { Socket } = require("net");
      const { Connection } = require("./connection");
      
      class Client extends Connection {
        connected = false;
        constructor() {
          super(new Socket());
        }
        connect(host, port) {
          this.socket.connect(port, host);
          this.socket.on("connect", () => {
            this.emit("connect");
          });
        }
      }
      
      const client = new Client();
      client.connect("localhost", 5052);
      client.on("message", (message) => {
        message.value += " from client";
        client.flush(message.encode());
      });
        撰写回答

        登录后参与交流、获取后续更新提醒

        相似问题
        推荐文章