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。
额外排查要点
确认跨域配置正确:确保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();检查连接URL协议:必须使用
ws://(非加密)或wss://(加密),不能用http://,否则浏览器会按HTTP请求发送,导致协议不匹配。
内容的提问来源于stack exchange,提问作者Jean-Luc Aubert
相关产品推荐
相关产品推荐

