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

Dart WebSocket的pingInterval工作机制及连接异常问题咨询

Dart WebSocket pingInterval 不生效问题:连接因1001状态码断开

设置客户端WebSocket的pingInterval后,服务器未响应PING帧,连接最终以状态码1001("Going Away")关闭。

示例代码

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math';

void main() async {
  final addr = InternetAddress('0.0.0.0', type: InternetAddressType.IPv4);

  Server.start(addr);

  final client = await Client.connect(addr);
  await client.listen();
  print('Script done');
}

class Server {
  Server._(this._server) {
    init();
  }

  final HttpServer _server;

  Future<void> init() async {
    await for (final request in _server) {
      final socket = await WebSocketTransformer.upgrade(request);
      print('[Server] Waiting for requests');

      await for (final payload in socket) {
        print('[Server] Incoming request: $payload');
        print('[Server] Waiting 5 seconds before sending a response');
        await Future.delayed(const Duration(seconds: 5));
        socket.add('Hello from Server');
      }
    }
  }

  static Future<Server> start(InternetAddress adr) async {
    final server = await HttpServer.bind(adr, 7444);

    return Server._(server);
  }
}

class Client {
  Client._(this._socket) {
    _socket.done.then((_) => print('Socket was done'));
  }

  final WebSocket _socket;

  Future<void> listen() async {
    _socket.add('Hello from Client');

    await for (final String payload in _socket) {
      print('Client incoming payload: $payload');
    }

    print('Close code: ${_socket.closeCode}');
    if (_socket.closeCode == WebSocketStatus.goingAway) {
      print('Code was "Going Away", meaning the server did not respond to set pingInterval');
    }
  }

  static Future<WebSocket> _createWebSocket(InternetAddress adr) async {
    final r = Random();
    final key = base64.encode(List<int>.generate(8, (_) => r.nextInt(256)));
    final client = HttpClient();
    client.connectionTimeout = const Duration(seconds: 6);
    final uri = Uri.parse('http://${adr.address}:7444');
    print('Connecting to ${uri}');
    final request = await client.getUrl(uri);
    request.headers.add('Connection', 'upgrade');
    request.headers.add('Upgrade', 'websocket');
    request.headers.add('sec-websocket-version', '13');
    request.headers.add('sec-websocket-key', key);

    final response = await request.close();
    final socket = await response.detachSocket();

    return WebSocket.fromUpgradedSocket(socket, serverSide: false);
  }

  static Future<Client> connect(InternetAddress adr) async {
    final socket = await Client._createWebSocket(adr)
      ..pingInterval = const Duration(seconds: 2);

    return Client._(socket);
  }
}

运行方式

将上述代码保存为test.dart文件,执行命令:

dart test.dart

问题详情

根据Dart文档,设置2秒的pingInterval时,客户端会在2秒后发送PING帧,并等待2秒接收服务器的PONG帧。但实际测试出现以下现象:

  • 当服务器未主动发送数据(示例中服务器5秒后才回复),客户端未收到PONG帧,连接直接断开
  • 若将pingInterval设为5秒,服务器刚好在5秒后回复业务数据,连接则不会断开

这一逻辑不符合预期:PING/PONG机制应该是WebSocket协议层自动处理的,无需依赖服务器的显式业务回复。

疑问

  1. 是否在代码实现中有操作错误?
  2. 如何让PING/PONG逻辑在无需服务器显式回复的情况下正常运行?

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 12:10:00