【问题标题】:React Socket.IO-Client not compatible with NodeJS (express) WebSockets?React Socket.IO-Client 与 NodeJS (express) WebSockets 不兼容?
【发布时间】:2018-12-17 11:03:35
【问题描述】:

我无法追踪为什么我的 react 客户端应用程序发出的信号没有到达 localhost 套接字服务器。我正在使用我修改为通过套接字接收客户端事件 (https://github.com/BlackConure/puppyjs) 的 PuppyJS 的分叉副本。

我可以使用 Apic Chrome 浏览器扩展程序并通过 Web 套接字连接到服务器端并发送/接收消息,但是当我尝试通过 React 中的客户端应用程序连接时,连接似乎工作,但是发射什么都不做。

我在客户端启用了 localstorage.DEBUG='*',它没有显示 socket.io 发生的任何事情。我还使用 --disable-web-security 启动了 chrome,以消除 CORS 问题的可能性;所以所有迹象都表明问题出在我的客户端设置上。

这里是配置:

为了确保套接字没有尝试重新使用现有的 (3006) 连接,我还尝试了 forceNew。还是不行。

var socket = io.connect('ws://localhost:3000', {
        path: '/ws',
        transports: [ 'websocket' ],
        forceNew: true
    });

    console.log(socket);

    socket.on('connect', function() {
        alert('connect');
    });

    socket.on('event', function(data) {
        alert('event');
        console.log(data);
    });

    socket.on('disconnect', function() {
        alert('disconnect');
    });

    socket.on('error', function(data) {
        console.log(data || 'error');
    });

    socket.on('connect_failed', function(data) {
        console.log(data || 'connect_failed');
    });

    socket.emit('LOGIN', 'Testing 123');
    newstate.socket = socket;
    return newstate;

即使在服务器端,我从客户端应用程序获得了连接,但它似乎永远不会发出。

当我检查套接字对象时,io.readyState 说打开;所以我认为服务器的响应一定有问题。我做了一个 RawCap & Wireshark 转储,发现客户端收到 HTTP 101 Switching Protocols 响应(与 Apic 中相同);但之后什么都没有发生。

我跟踪了发射,它正在将 LOGIN 扔到请求缓冲区中(因为 connected=false),我假设这是因为它没有处于就绪状态。

这毫无意义,所以我使用 Socket.IO 作为服务器启动了一个简单的 NodeJS 服务器,一切正常!

这是否意味着 Socket.IO 和 WebSockets 不兼容,还是我做了一些愚蠢的事情?我认为 Socket.io 应该能够处理不同的协议。 David Walsh 的文章 (https://davidwalsh.name/websocket) 指出:

Socket.IO 简化了 WebSocket API 并统一了其 API 后备运输。运输包括:

  • WebSocket
  • 闪存插座
  • AJAX
  • 长轮询 AJAX
  • 多部分流式传输
  • IFrame
  • JSONP 轮询

我错过了什么吗?如果这些不兼容,这是否意味着我们现在必须根据通信层进行不同的编码?

【问题讨论】:

  • socket.io 在这些传输之上实现了自己的协议。你总是需要服务器和客户端来使用它。 Read here how to use the server implementation of socket.io。如果你想要普通的 websockets,你也可以使用WebSocket API。但是然后你例如必须在此基础上实现自己的订阅机制,并且您没有像 socket.io 那样针对不受支持的客户端的智能后备策略。
  • @trixn 我知道文档以及如何使用 socket.io 设置客户端和服务器,但我认为至少在套接字级别你会有一些一致性。当然,您需要与服务器和客户端之间的消息传递协议保持一致,但我认为 Socket.IO 涵盖了基本的连接/发送/接收,特别是考虑到它处理多种传输。
  • 我想 socket.io 客户端希望服务器能做出更多响应,而不仅仅是HTTP 101 以进入就绪状态并能够交换消息。但这需要了解 socket.io 协议的内部结构。您可以使 socket.io 服务器与客户端通信并使用wireshark(或仅在chrome 网络选项卡中)进行检查。我想你会期待更多的事情发生。
  • 我做了一个 rawcap 和 wireshark,他们的反应完全一样……唯一不同的是他们返回的 websocket 密钥。两者之间的情况有所不同,但我认为这更多是关于一个独特的令牌,而不是对建立连接的标识。

标签: node.js reactjs websocket socket.io


【解决方案1】:

这是否意味着 Socket.IO 和 WebSockets 不兼容? 我做了一些愚蠢的事情吗?我以为 Socket.io 应该是 能够处理不同的协议。

Socket.io 在 websocket 之上运行。就像您在询问电话(websockets)和日语(socket.io)是否兼容。你无法回答这个问题,因为这是两个不同的通信层。因此,仅仅因为 socket.io-client 使用 websockets 与服务器通信,并不意味着他可以与只知道如何建立 websocket 连接(电话)的服务器交换消息,而不能说 socket.io 协议(日语)在它上面。

您可能想要使用浏览器原生的WebSocket API,它已经提供了一个抽象来建立连接以及发送/接收消息。

当然,如果您的应用需要,您必须自己实施重新连接和重试策略以及后备传输。这就是 socket.io 开箱即用的功能。

【讨论】:

  • 谢谢,这很有帮助。我曾假设 Socket.io 只是在幕后利用 websockets 以及所有重试和附加协议支持,但它仍将使用底层 websocket api。本质上,WebSocket API 是电话线,您可以在其中使用任何您想要的语言,只要另一端也能说话。那你告诉我的是,当你打电话时,运营商不会直接将你连接到呼叫方,你也必须先通过某种形式的运营商。
猜你喜欢
  • 2021-03-26
  • 1970-01-01
  • 2020-08-22
  • 1970-01-01
  • 2018-05-18
  • 2016-06-23
  • 2012-11-07
  • 2011-09-15
  • 1970-01-01
相关资源
最近更新 更多