简体   繁体   English

Socket.io“连接”事件是否可以安全收听?

[英]Is Socket.io “connect” event even safe to listen to?

I've been skeptical about this for years. 我对此一直持怀疑态度。 The common practice is making a Socket and then listening to its "connect" event. 常见的做法是制作一个Socket然后侦听其"connect"事件。 It doesn't sound very safe. 听起来不是很安全。

import io from "socket.io-client";
CONNECT: const socket = io(……);
// ← An asynchronous connection establishment might happen here, no?
LISTEN: socket.on("connect", ……);

It tries to establish a connection as soon as the CONNECT statement gets executed. 一旦 CONNECT语句被执行,它将尝试建立连接。 What if it does, before LISTEN ? 如果可以, LISTEN 之前怎么办?

What makes such a practice safe to be used? 是什么使这种做法可以安全使用? What I believe is that just because it is two consecutive statements doesn't mean an asynchronous connection establishment cannot happen in-between. 我相信,仅仅因为它是两个连续的语句,并不意味着异步连接建立不会在两者之间发生。 Are my thoughts wrong? 我的想法错了吗?


EDIT: internal code investigation. 编辑:内部代码调查。

I've just read the source code of socket.io-client and drawn a conclusion that the only code-wise safe way to go is to turn the autoConnect option off for io() not to create a Socket that automatically tries to establish a connection, which leads to arbitrary (“possibly-untimely”) emission of the "connect" event. 我刚刚阅读了socket.io-client的源代码,并得出了一个结论,即代码上唯一安全的方法是关闭io()autoConnect选项,而不是创建一个自动尝试建立Socket连接,导致任意(“可能不及时”)发出"connect"事件。 This requires a manual call to socket.open() but is safe. 这需要手动调用socket.open()但很安全。

Here's how it goes: 这是怎么回事:

  1. io() creates a Manager instance and calls .socket() of it . io() 创建一个Manager实例调用.socket()

  2. The .socket() creates a new Socket instance and then binds the Manager 's own internal handlers (that is not users') for "connecting" and "connect" events . .socket() 创建一个新的Socket实例然后为"connecting""connect"事件绑定Manager自己的内部处理程序(不是用户的)

  3. Since the Socket 's constructor .open() s if autoConnect , which involves the immediate emission of a "connecting" event and the future emission of a "connect" event , the Manager calls its own internal "connecting" event handler manually if autoConnect . 由于Socket的构造函数.open()如果为autoConnect ,则涉及立即发出"connecting"事件以及将来发出"connect"事件 ,因此如果使用autoConnect ,则Manager 将手动调用内部的"connecting"事件处理程序

Turned out new Socket never waits for you 原来是new Socket从来没有等你

I could not find any safe-guard gizmo (at least code-wise ) to keep an autoConnect -ing Socket from establishing a "connect" -ion until corresponding handlers get attached. 我找不到任何安全的小控件(至少在代码方面是如此 ),以防止autoConnect -ing Socket建立"connect" -ion,直到"connect"相应的处理程序为止。

The internal implementation is also making this assumption 内部实现也做出了这样的假设

What's funny is that even Manager does this dangerous practice, 有趣的是,即使是Manager也进行了这种危险的做法,

Manager.prototype.socket = function (nsp, opts) {
  var socket = this.nsps[nsp];
  if (!socket) {
    socket = new Socket(this, nsp, opts);
    this.nsps[nsp] = socket;
    var self = this;
    socket.on('connecting', onConnecting);
    socket.on('connect', function () {
      socket.id = self.generateId(nsp);
    });

    if (this.autoConnect) {
      // manually call here since connecting event is fired before listening
      onConnecting();
    }
  }

  function onConnecting () {
    if (!~indexOf(self.connecting, socket)) {
      self.connecting.push(socket);
    }
  }

  return socket;
};

making an assumption that a Socket , with the autoConnect option being true or not, 假设SocketautoConnect选项为true

socket = new Socket(this, nsp, opts);

won't get to "connect" before 之前不会"connect"

socket.on('connect', function () {
  socket.id = self.generateId(nsp);
});

.

Are there any good reasons to make this assumption, aside from “the code path to handler-attaching just looks shorter (“cheaper”) than that of connection establishment?” How come this is not a race condition ? 除了“到处理程序附加的代码路径看起来比连接建立的路径看起来更短(“便宜”)之外,是否有充分的理由进行此假设?”这怎么不是竞争条件呢?

You need an EventEmitter before to attach a connect event, additionally the socket.io-client library manages this scenario, take a look on: 在附加connect事件之前,您需要一个EventEmitter,另外,socket.io-client库管理这种情况,请看一下:

https://github.com/socketio/socket.io-client/blob/master/lib/manager.js#L378 https://github.com/socketio/socket.io-client/blob/master/lib/manager.js#L378

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM