net.Socket 类不包含pid信息

我通过 net 模块创建一个 IPC 服务器,希望实现多进程间的通信,但是请求过来的 socket 实例不携带进程的 pid 信息,因此我需要再发次请求定义它的pid,代码如下

  1. // server.js
  2. const clientList: IClient[] = []
  3. enum MSG_TYPE {
  4. INIT,
  5. DATA,
  6. COMMUNICATE
  7. }
  8. interface IClient {
  9. id: number | string
  10. socket: net.Socket
  11. }
  12. const handleClientMsg = (msg, current) => {
  13. switch (msg.type) {
  14. case MSG_TYPE.INIT:
  15. let client = clientList.find(item => item.socket === current)
  16. if (client) {
  17. client.id = msg.id
  18. }
  19. break
  20. case MSG_TYPE.COMMUNICATE: {
  21. let client = clientList.find(item => item.id === msg.id)
  22. if (client) {
  23. client.socket.write(msg.data)
  24. }
  25. }
  26. break
  27. default:
  28. break
  29. }
  30. }
  31. server.on('connection', socket => {
  32. clientList.push({ id: undefined, socket })
  33. socket.on('data', function (msg) {
  34. let message = JSON.parse(msg.toString())
  35. handleClientMsg(message, this)
  36. })
  37. })
  1. // client.js
  2. const client = net.connect(DEBUG, () => {
  3. log(chalk.green('服务已连接——' + '当前进程ID为:' + process.pid))
  4. client.write(JSON.stringify({ id: process.pid, type: MSG_TYPE.INIT, data: {} }))
  5. client.write(JSON.stringify({ id: 17284, type: MSG_TYPE.COMMUNICATE, data: 'Hello client' }))
  6. })

在 connection 事件中请求的 socket 没有能够确定身份的唯一信息,因此我第一次只是存储了这个 socket,接着我让客户端发送了一个信息,这个信息携带了它的 pid,我再把这个 pid 与之前的 socket 绑定,这样接下来就能够和请求在 IPC服务器的其它客户端进行通信了。 这个现象只存在 IPC服务器中,在 TCP服务器中,可以通过 socket 的address相关信息确定它的身份

类上绑定事件时不应该使用箭头函数

这个问题同样出现在使用 装饰器编写切面函数,使用箭头函数以后,导致方法内的this指向不对

  1. server.on('connection', socket => {
  2. clientList.push({ id: undefined, socket })
  3. // socket.on('data', msg => {
  4. // let message = JSON.parse(msg.toString())
  5. // handleClientMsg(message, this)
  6. // console.log(this, this === socket) // false
  7. // log(chalk.green(clientList.map(item => item.id).toString()))
  8. // })
  9. socket.on('data', function (msg) {
  10. let message = JSON.parse(msg.toString())
  11. handleClientMsg(message, this)
  12. console.log(this, this === socket) // true
  13. log(chalk.green(clientList.map(item => item.id).toString()))
  14. })
  15. })

在注释的代码中,使用了箭头函数,导致this指向不对,只能传递 socket,改为普通的function以后就可以使用this了。值得注意的是,在 socket 的data事件内部,这里的socket是来自connection事件传递过来的socket,每一个请求的 socket 是不同的,说明这里形成了闭包