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

Flutter通过WebSocket对接Node.js Socket.IO服务器通信失败求助

问题根源:协议不兼容

你遇到的核心问题很明确:Flutter端用的是标准WebSocket协议,但Node.js端用的是Socket.IO框架——Socket.IO并不是纯粹的WebSocket实现,它在标准协议之上封装了自定义的握手、心跳、事件机制,原生WebSocket客户端根本没法和它直接通信,这就是为什么你发消息收不到反馈的原因。

下面给你两种可行的解决方案,按需选择:


方案1:Node.js改用标准WebSocket库

如果你想继续用Flutter的原生WebSocket,那Node.js端需要换成标准WebSocket实现,比如ws库:

  1. 先安装依赖:
npm install ws
  1. 修改Node.js服务器代码:
const express = require('express');
const http = require('http');
const WebSocket = require('ws');

const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });

app.get('/', (req, res) => {
  res.send('hey people');
});

// 处理WebSocket连接与消息
wss.on('connection', (ws) => {
  console.log('a user connected');

  // 接收客户端消息并主动回复
  ws.on('message', (message) => {
    console.log(`received: ${message}`);
    ws.send(`Server echo: ${message}`);
  });

  // 监听断开连接
  ws.on('close', () => {
    console.log('user disconnected');
  });
});

const PORT = process.env.PORT || 3000;
server.listen(PORT, () => console.log(`app started on port ${PORT}`));

你的Flutter客户端代码完全不需要修改,直接运行就能实现双向通信——客户端发消息后,服务器会立即回复,Flutter的StreamBuilder也能实时接收到回复内容。


方案2:Flutter使用Socket.IO客户端库

如果想保留Node.js的Socket.IO服务器,那Flutter端需要用对应的Socket.IO客户端库,而不是原生WebSocket:

  1. 在Flutter项目的pubspec.yaml中添加依赖:
dependencies:
  flutter:
    sdk: flutter
  socket_io_client: ^2.0.3 # 可替换为最新兼容版本
  1. 修改Flutter客户端代码:
import 'package:flutter/material.dart';
import 'package:socket_io_client/socket_io_client.dart' as IO;

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = 'Socket.IO Demo';
    // 初始化Socket.IO连接,指定用WebSocket传输
    final socket = IO.io('http://localhost:3000', <String, dynamic>{
      'transports': ['websocket'],
      'autoConnect': true,
    });
    return MaterialApp(
      title: title,
      home: MyHomePage(title: title, socket: socket),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;
  final IO.Socket socket;

  const MyHomePage({Key? key, required this.title, required this.socket})
      : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final TextEditingController _controller = TextEditingController();
  String _receivedMessage = '';

  @override
  void initState() {
    super.initState();
    // 监听服务器发来的消息
    widget.socket.on('message', (data) {
      setState(() {
        _receivedMessage = data.toString();
      });
    });

    // 监听连接状态
    widget.socket.onConnect((_) => print('connected to server'));
    widget.socket.onDisconnect((_) => print('disconnected from server'));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            TextFormField(
              controller: _controller,
              decoration: const InputDecoration(labelText: 'Send a message'),
            ),
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 24.0),
              child: Text(_receivedMessage.isNotEmpty ? _receivedMessage : ''),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _sendMessage,
        child: const Icon(Icons.send),
      ),
    );
  }

  void _sendMessage() {
    if (_controller.text.isNotEmpty) {
      widget.socket.emit('message', _controller.text);
      _controller.clear();
    }
  }

  @override
  void dispose() {
    widget.socket.disconnect();
    _controller.dispose();
    super.dispose();
  }
}
  1. 同时完善Node.js的Socket.IO服务器,添加消息处理逻辑:
const express= require('express');
const app= express();
const http=require('http');
const socketio= require('socket.io');
const server= http.createServer(app);
const io=socketio(server);

app.get('/',(req,res)=>{
 res.send('hey people')
})

const PORT= process.env.PORT||3000;

io.on('connection', (socket) => {
 console.log('a user connected');

 // 监听客户端的'message'事件并回复
 socket.on('message', (msg) => {
   console.log(`received: ${msg}`);
   socket.emit('message', `Server received: ${msg}`);
 });

 socket.on('disconnect', () => {
   console.log('user disconnected');
 });
});

server.listen(PORT,()=> console.log(`app started on port ${PORT}`));

这样两端就用统一的Socket.IO协议通信,能正常收发消息了。


额外注意事项

  • 真机测试时,不要用localhost,换成你的电脑局域网IP(比如192.168.x.x),确保手机和电脑在同一网络下。
  • 注意Socket.IO客户端和服务器的版本兼容性,比如服务器用v4的话,客户端也要对应使用支持v4的socket_io_client版本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 09:57:54