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

Angular5结合socket.io-client与Ratchet Websocket通信时遇HTTP 426错误

解决Angular应用连接Ratchet WebSocket时的HTTP 426错误

这个HTTP 426(Upgrade Required)错误的核心原因是你用错了客户端库——Ratchet是遵循RFC 6455标准的WebSocket服务器,而socket.io-client并不是原生WebSocket客户端,它有自己专属的协议层(包括自定义握手流程、帧格式),和标准WebSocket完全不兼容,所以服务器会返回426错误,提示你需要使用正确的协议进行升级。

解决方案1:改用Angular原生WebSocket API(推荐)

既然你的服务器是标准WebSocket实现,直接用浏览器原生的WebSocket API就能完美兼容,不需要依赖socket.io-client。下面是改造后的Angular服务示例:

import { Injectable } from '@angular/core';
import { Subject, Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class WebSocketService {
  private socket: WebSocket;
  private messageSubject = new Subject<any>();

  constructor() {
    this.initConnection();
  }

  private initConnection(): void {
    // 注意用ws://协议,不是http://
    this.socket = new WebSocket('ws://192.168.1.99:8080');

    this.socket.onopen = () => {
      console.log('WebSocket连接成功建立');
    };

    this.socket.onmessage = (event) => {
      // 根据服务器返回的数据格式解析,这里假设是JSON
      try {
        const message = JSON.parse(event.data);
        this.messageSubject.next(message);
      } catch (error) {
        console.error('解析消息失败:', error);
        this.messageSubject.next(event.data);
      }
    };

    this.socket.onerror = (error) => {
      console.error('WebSocket连接出错:', error);
    };

    this.socket.onclose = (event) => {
      console.log('WebSocket连接关闭,代码:', event.code, '原因:', event.reason);
      // 可选:添加断线自动重连逻辑
      setTimeout(() => this.initConnection(), 3000);
    };
  }

  sendMessage(message: any): void {
    if (this.socket.readyState === WebSocket.OPEN) {
      // 转为JSON字符串发送,和服务器端格式保持一致
      this.socket.send(JSON.stringify(message));
    } else {
      console.warn('WebSocket未处于连接状态,无法发送消息');
    }
  }

  getMessages(): Observable<any> {
    return this.messageSubject.asObservable();
  }
}

解决方案2:如果非要使用socket.io,替换服务器端实现

如果你坚持要用socket.io-client,那你的PHP服务器必须换成支持socket.io协议的实现,因为socket.io需要客户端和服务器端都使用它的专属协议。你可以选择:

  • workerman/socket.io:一个成熟的PHP socket.io服务器实现
  • 或者使用Ratchet的socket.io扩展(不过维护性不如前者)

这种方案需要你重构服务器端代码,适配socket.io的协议,所以除非有特殊需求,更推荐方案1。

额外排查要点

  1. 确认跨域配置正确:确保Ratchet服务器允许http://localhost:4200的跨域请求,正确的做法是使用Ratchet的OriginChecker中间件:

    use Ratchet\Server\IoServer;
    use Ratchet\Http\HttpServer;
    use Ratchet\WebSocket\WsServer;
    use Ratchet\Middleware\OriginChecker;
    use YourApp\YourWebSocketHandler;
    
    $wsServer = new WsServer(new YourWebSocketHandler());
    $httpServer = new HttpServer($wsServer);
    // 添加Origin检查中间件,允许指定域名
    $httpServer->addMiddleware(new OriginChecker(['http://localhost:4200']));
    
    $server = IoServer::factory($httpServer, 8080);
    $server->run();
    
  2. 检查连接URL协议:必须使用ws://(非加密)或wss://(加密),不能用http://,否则浏览器会按HTTP请求发送,导致协议不匹配。

内容的提问来源于stack exchange,提问作者Jean-Luc Aubert

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:24:36