Flutter应用连接WebSocket时出现升级失败错误的求助
看起来你遇到的WebSocketException: Connection was not upgraded to websocket错误,主要是几个配置不匹配导致的,我帮你逐一拆解:
1. 端口不匹配
你的客户端代码里连接的是http://localhost:8080/v1,但服务端代码明确设置了端口为7070(app.set("port", process.env.PORT || 7070);),端口不一致直接导致连接请求找不到正确的服务端端点,自然无法完成WebSocket升级。
额外提醒:如果是Android模拟器,不要用localhost,因为模拟器的localhost指向自身,你需要换成10.0.2.2来访问电脑本地的服务;iOS模拟器可以直接用localhost。
2. 路径配置错误
客户端连接时加了/v1路径,但你的服务端Socket.IO默认挂载在根路径的/socket.io端点下。如果没有在服务端配置Socket.IO挂载到/v1,客户端请求的路径就找不到对应的Socket.IO处理逻辑,导致握手失败。
3. Socket.IO版本兼容性问题
如果你的服务端socket.io版本和客户端socket_io_client版本不匹配,也会出现握手失败、无法升级WebSocket的情况。比如服务端用v4.x,客户端用v2.x,两者的协议格式有差异,会导致连接失败。
具体解决方案
步骤1:修正客户端连接地址
把客户端的连接代码改成:
// Android模拟器用10.0.2.2,iOS模拟器直接用localhost,端口统一为服务端的7070 IO.Socket socket = IO.io('http://10.0.2.2:7070', OptionBuilder().setTransports(['websocket']).build());
步骤2:检查并对齐Socket.IO版本
- 查看服务端版本:在服务端项目根目录运行
npm list socket.io,记下版本号(比如4.6.1) - 客户端在
pubspec.yaml里指定对应的socket_io_client版本,比如服务端是v4.x,客户端就用^4.0.0的版本:
dependencies: socket_io_client: ^4.6.1
然后运行flutter pub get更新依赖。
步骤3:修复客户端代码的小错误
你客户端里的socket.on('event', (data) => streamSocket.addResponse);没有把接收到的data传递给addResponse,应该改成:
socket.on('event', (data) => streamSocket.addResponse(data.toString()));
(因为addResponse需要接收一个String类型参数,所以把data转成字符串)
步骤4:验证服务端Socket.IO的挂载配置(可选)
如果你的服务端确实需要把Socket.IO挂载到/v1路径,可以修改服务端代码:
// 把原来的var io = require("socket.io")(http);改成: var io = require("socket.io")(http, { path: "/v1/socket.io" });
这样客户端连接http://xxx:7070/v1就能正确匹配了,但如果没有这个需求,建议保持默认路径,去掉客户端的/v1。
按照这些步骤调整后,应该能解决WebSocket升级失败的问题。你可以先从端口和路径的修正开始,这是最常见的原因。
内容的提问来源于stack exchange,提问作者Emir Kutlugün

