Flutter 真机调试时 Socket.io 连接本地后端无响应问题
真机Socket连接失效问题排查方案
第一步:修正连接地址的网段错误
- 当前代码里使用的
192.168.56.1是Windows系统下VirtualBox、VMware等虚拟机软件创建的专用内部网卡地址,该地址仅对电脑本机、电脑上运行的虚拟机生效,连接同一WiFi的实体手机完全无法通过这个IP访问到你的后端服务 - 正确操作:
- 在电脑网络设置中找到和手机处于同一局域网的无线网卡真实IP(Windows可执行
ipconfig查看无线适配器的IPv4地址,Mac/Linux可执行ip a查看wlan接口的IPv4地址,正常网段一般为192.168.0.x、192.168.1.x、10.0.0.x这类和手机WiFi网段一致的地址) - 先在手机浏览器中输入
http://<替换后的IP>:3000,能正常返回后端public目录的静态页面,才说明网络通路是打通的 - 把Flutter端代码里的连接地址替换成这个真实局域网IP
- 在电脑网络设置中找到和手机处于同一局域网的无线网卡真实IP(Windows可执行
第二步:放开平台端的明文网络请求限制
- Android 平台:
检查android/app/src/main/AndroidManifest.xml配置:- 确保已添加基础权限:
<uses-permission android:name="android.permission.INTERNET" /> - 如果项目的
targetSdkVersion≥28,需要在<application>节点添加android:usesCleartextTraffic="true",否则系统会默认拦截所有HTTP明文请求,包括WebSocket的明文连接
- 确保已添加基础权限:
- iOS 平台:
检查ios/Runner/Info.plist配置,添加ATS权限放开本地HTTP访问:<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>
第三步:排查本地防火墙拦截
- Windows Defender、系统自带防火墙、第三方安全软件默认会拦截非本机发起的3000端口入站请求,这种场景下本机Web端能正常连接,不代表局域网内的其他设备能访问到服务
- 可临时关闭本地防火墙测试连接是否恢复,若恢复则给Node.js进程添加3000端口的局域网入站允许规则即可
第四步:修复Socket实例的内存回收隐患
- 当前代码中socket是
_initConfig方法内的局部变量,方法执行完成后,若没有其他强引用持有这个实例,会被Dart的垃圾回收机制回收,直接表现为没有任何事件回调、连接静默失败 - 修复方式:将socket提升为类成员变量,跟随服务类的生命周期存在,示例代码:
class SocketService with ChangeNotifier { ServerStatus _serverStatus = ServerStatus.Connecting; // 提升为类成员,避免被GC回收 late final IO.Socket socket; SocketService() { _initConfig(); } void _initConfig() { socket = IO.io('http://<你的真实局域网IP>:3000/', <String, dynamic>{ 'transports': ['websocket'], 'autoConnect': true, 'forceNew': true, }); socket.on('connect', (_) => print('connect')); socket.on('disconnect', (_) => print('disconnect')); } } - 额外注意:前后端的socket.io协议版本要完全匹配,比如后端使用socket.io v2.x版本时,Flutter端依赖的
socket_io_client也要使用对应的2.x版本,版本不兼容会导致握手失败、无任何回调的问题
内容的提问来源于stack exchange,提问作者Johan David
相关产品推荐
相关产品推荐

