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

黄杉真丑
  • 0
新手上路,请多包涵

先上个图
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客户端如何管理。存在一个全局集合?可能会有内存泄露的风险。
水平有限,表达的可能有问题。不知道老哥们是否明白。小弟再此磕头了,砰砰砰砰!!!望指导

评论
阅读 326
2 个回答

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());
});
撰写回答

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

宣传栏