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

Flutter Web端InternetAddress.lookup报Unsupported operation错误解决

报错根因

dart:io 提供的 InternetAddress.lookup 是基于原生系统套接字实现的DNS查询能力,Web端运行在浏览器安全沙箱中,没有底层套接字操作权限,也不支持直接发起自定义DNS查询。不管是直接引用dart:io还是使用universal_io做兼容层,都没法绕过浏览器的这个限制,所以必然抛出不支持操作的错误。

适配方案

核心思路是按运行平台拆分检测逻辑,保留原有移动端/桌面端的可靠检测逻辑,Web端单独使用浏览器支持的HTTP探测方式实现连通性判断,对外统一输出状态流,上层业务无需感知平台差异。

  • 引入foundation库的kIsWeb常量做平台分支判断,不要在Web环境下调用任何dart:io相关的网络API
  • Web端放弃DNS探测方案,改用带超时的HEAD请求做连通性校验,优先使用自有业务服务的健康检查接口,避免第三方公共地址的跨域拦截问题
  • 保留原有connectivity_plus的网络状态变化监听逻辑,在网络切换事件触发时重新执行连通性校验,和原有移动端行为对齐
  • 可直接引入官方维护的跨平台http库实现探测请求,无需单独处理Web端原生API的条件导入问题,兼容全平台编译

修正后完整实现代码

首先在pubspec.yaml中添加依赖:

dependencies:
  http: ^1.1.0 # 跨平台HTTP请求库,适配Web/移动端/桌面端
  connectivity_plus: ^5.0.0
  rxdart: ^0.27.7

服务层实现代码:

import 'dart:async';
import 'dart:io' show SocketException, InternetAddress;
import 'package:flutter/foundation.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:rxdart/rxdart.dart';
import 'package:http/http.dart' as http;

enum ConnectionStatus {
  online,
  offline,
}

class CheckInternetConnection {
  final Connectivity _connectivity = Connectivity();
  // 替换为自有业务域名,避免第三方地址跨域拦截
  static const String _probeAddress = 'www.your-business-domain.com';
  static const Duration _probeTimeout = Duration(seconds: 3);

  /// 初始状态默认设为在线
  final _controller = BehaviorSubject.seeded(ConnectionStatus.online);
  StreamSubscription? _connectionSubscription;

  CheckInternetConnection() {
    _checkInternetConnection();
  }

  Stream<ConnectionStatus> internetStatus() {
    _connectionSubscription ??= _connectivity.onConnectivityChanged
        .listen((_) => _checkInternetConnection());
    return _controller.stream;
  }

  Future<void> _checkInternetConnection() async {
    try {
      // 网络切换后短暂等待,避免网卡刚启动时网络未就绪导致误判
      await Future.delayed(const Duration(milliseconds: 300));
      
      bool isOnline = false;
      if (kIsWeb) {
        // Web端走HTTP探测逻辑
        final response = await http
            .head(Uri.parse('https://$_probeAddress/health'))
            .timeout(_probeTimeout);
        isOnline = response.statusCode >= 200 && response.statusCode < 300;
      } else {
        // 移动端/桌面端保留原有轻量DNS探测逻辑
        final result = await InternetAddress.lookup(_probeAddress)
            .timeout(_probeTimeout);
        isOnline = result.isNotEmpty && result[0].rawAddress.isNotEmpty;
      }

      _controller.sink.add(isOnline 
          ? ConnectionStatus.online 
          : ConnectionStatus.offline);
    } on SocketException catch (_) {
      _controller.sink.add(ConnectionStatus.offline);
    } on TimeoutException catch (_) {
      _controller.sink.add(ConnectionStatus.offline);
    } catch (_) {
      _controller.sink.add(ConnectionStatus.offline);
    }
  }

  Future<void> close() async {
    await _connectionSubscription?.cancel();
    await _controller.close();
  }
}
注意事项
  • Web端做HTTP探测时,如果使用第三方公共地址,大概率会触发浏览器CORS跨域限制导致请求被拦截,出现离线误判,必须使用自有业务域名下的接口,且服务端配置好对应跨域响应头
  • 探测超时时间建议设置在2-5秒区间,过短会在弱网环境下频繁误判,过长会导致网络状态更新延迟
  • connectivity_plus在Web端的状态监听基于浏览器原生online/offline事件,该事件仅能反映设备是否接入局域网,无法判断是否能正常访问公网或业务服务,必须搭配主动探测逻辑才能保证检测结果准确

内容的提问来源于stack exchange,提问作者Neal Osva

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 15:06:25