You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Node.js的ws包连接Socket.io第三方服务器?

如何用ws包连接Socket.io服务器

嘿,这个问题我之前踩过坑!Socket.io可不是标准的WebSocket实现——它在原生WebSocket协议之上封装了自己的握手流程、心跳机制和消息格式,所以直接用ws包连默认的端点肯定会失败。咱们一步步来搞定它:

核心原因

Socket.io客户端和服务器之间会先通过HTTP请求完成握手,获取会话ID(sid),然后才会升级到WebSocket连接,而且连接URL需要带上特定的查询参数,还得遵循它的消息格式规范。

具体实现步骤

1. 先完成Socket.io握手,获取会话ID

你需要先发送一个HTTP GET请求到Socket.io的端点,带上EIO(版本号)和transport=polling的参数,从响应里提取出sid。

2. 用ws包连接正确的WebSocket URL

连接的URL格式应该是:

wss://api.example.com/1.0/scores/?EIO=4&transport=websocket&sid=你的会话ID

注意:EIO的版本要对应服务器的Socket.io版本,v4用EIO=4,v3用EIO=3,v2用EIO=2,版本不匹配会握手失败。

3. 处理Socket.io的初始化消息

连接成功后,Socket.io要求你先发送2probe,服务器会回复3probe,之后你发送5表示准备就绪,这样就能正常收发消息了。另外,Socket.io的消息都有前缀(比如42表示事件消息,2表示ping),需要解析前缀后的内容。

完整代码示例

const WebSocket = require('ws');
const fetch = require('node-fetch'); // 也可以用http模块替代

async function connectToSocketIoServer() {
  // 第一步:获取会话ID(sid)
  const handshakeUrl = 'https://api.example.com/1.0/scores/?EIO=4&transport=polling';
  const handshakeResponse = await fetch(handshakeUrl);
  const rawHandshakeData = await handshakeResponse.text();
  
  // 解析响应中的sid,响应格式类似:"0{"sid":"abc123","upgrades":["websocket"],...}"
  const sidMatch = rawHandshakeData.match(/"sid":"([^"]+)"/);
  if (!sidMatch) {
    throw new Error('无法从握手响应中获取会话ID');
  }
  const sid = sidMatch[1];

  // 第二步:建立WebSocket连接
  const wsUrl = `wss://api.example.com/1.0/scores/?EIO=4&transport=websocket&sid=${sid}`;
  const wsClient = new WebSocket(wsUrl);

  wsClient.on('open', () => {
    console.log('WebSocket已连接到Socket.io服务器');
    // 发送初始化probe消息
    wsClient.send('2probe');
  });

  wsClient.on('message', (data) => {
    const message = data.toString();
    console.log('收到消息:', message);

    // 处理probe回复
    if (message === '3probe') {
      wsClient.send('5');
      console.log('已发送就绪消息');
    }
    // 处理心跳ping,回复pong
    else if (message === '2') {
      wsClient.send('3');
    }
    // 处理事件消息(42开头)
    else if (message.startsWith('42')) {
      const [eventName, eventData] = JSON.parse(message.slice(2));
      console.log(`收到事件 ${eventName}:`, eventData);
      // 这里可以根据业务逻辑处理事件
    }
  });

  wsClient.on('error', (error) => {
    console.error('WebSocket错误:', error);
  });

  wsClient.on('close', () => {
    console.log('WebSocket连接已关闭');
  });
}

// 执行连接
connectToSocketIoServer().catch(console.error);

额外注意事项

  • 一定要匹配正确的EIO版本:可以通过查看服务器返回的HTTP响应头或者Socket.io文档确认版本。
  • 心跳处理:Socket.io会定期发送2(ping),你必须回复3(pong),否则服务器会主动断开连接。
  • 消息格式:所有事件消息都是42[事件名, 数据]的格式,需要去掉前缀42后再解析JSON。

内容的提问来源于stack exchange,提问作者Orbit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:41:14