恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Dart SDK 中的 Dart Development Service(DDS)实战指南:协议转发、SSE 通信与扩展 RPC 深度解析

  • 首页
  • 资讯中心
  • /
  • Dart SDK 中的 Dart Development Service(DDS)实战指南:协议转发、SSE 通信与扩展 RPC 深度解析

相关资讯

上下文反馈学习:不更新参数的大模型行为修正实战指南 2026/9/25 13:40:25
OpenClaw + Hermes 配 TaoToken:Vibe Coding 本地部署与云端协同的 config.toml 骨架 2026/9/25 13:40:25
如何让Skill同时跑在Cursor、Codex和Claude Code里?TaoToken统一Key配置实战 2026/9/25 13:40:25

最新资讯

华为杯数学建模实战:36小时备战流程与工具链工程化指南
linux笔记归纳20:网络层协议IP
DM服务注册
《WiFi 嵌入式物联网开发全套实战》| 第 19 章 ESP32 WiFi + MQTT 物联网上云完整工程
Qt style-sheet 样式不起作用?从 QLabel/QPushButton 到 TaoToken 配置排查
ctfshwo pwn入门栈收尾

今日推荐

AI元人文:从工具使用到思维重构的深度探索
Python+CNN车牌识别实战:从数据预处理到模型训练与部署
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

本周热门

BrewUI:给Homebrew套上图形界面,让macOS软件包管理更简单
BrewUI:让Homebrew包管理变得可视化与高效
公式与文本对齐全攻略:从Word到LaTeX的实用技巧

本月精选

自研推理加速器Redwood:两周内实现PyTorch模型高效部署的实战教程
V4L2摄像头采集实战:从camera_client.rar到出图全流程解析
从“谁发明了钢琴键”到知识问答智能体:RAG与记忆工程实践

Dart SDK 中的 Dart Development Service(DDS)实战指南:协议转发、SSE 通信与扩展 RPC 深度解析

发布时间:2026/9/25 13:45:25
Dart SDK 中的 Dart Development Service(DDS)实战指南:协议转发、SSE 通信与扩展 RPC 深度解析 编程语言编译器语言运行时标准库开发工具【免费下载链接】sdkThe Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.项目地址https://gitcode.com/gh_mirrors/sdk1/sdk点击查看免费下载本篇指南以 Dart SDK 仓库中pkg/dds包及其 README 为核心系统讲解 Dart Development ServiceDDS的定位、核心工作原理、基于 SSE 的客户端接入方式以及 DDS Protocol 2.1 中全部公开 RPC 与数据类型。读完本文你将掌握如何启动 DDS、如何让既有 VM Service 客户端HTTP / WebSocket / SSE透明地访问 DDS 实例、如何利用 DDS 的流历史与暂停/恢复审批机制实现 DevTools、IDE 等工具链能力并能结合源码理解请求转发与认证的底层实现。一、DDS 是什么VM Service 之上的开发服务层DDSDart Development Service是 Dart SDK 中用于孵化 Dart VM Service 的配套服务。它的角色定位非常清晰DDS 是一个位于 Dart VM Service 与 VM Service 客户端之间的中间层intermediary在完整实现 VM Service 协议的基础上额外提供核心 VM Service 协议所没有的扩展能力。在pkg/dds/lib/dds.dart的类注释中DartDevelopmentService被描述为An intermediary between a Dart VM service and its clients that offers additional functionality on top of the standard VM service protocol.也就是说DDS 本身并不重新实现调试/性能采样等 VM 底层能力而是代理forwardVM Service 协议的请求到真实的 VM Service直接处理 DDS 协议Dart Development Service Protocol的请求为客户端提供 HTTP、WebSocket、SSE 三种通信形态的统一入口。从pkg/dds/pubspec.yaml可以看到它的依赖面json_rpc_2、shelf、shelf_proxy、shelf_web_socket、sse、vm_service、web_socket_channel等这正对应了它HTTP 服务 JSON-RPC 转发 SSE/WS 双通道的技术骨架。1.1 与 VM Service 的分工DDS 协议pkg/dds/dds_protocol.md开宗明义This protocol is an extension of the Dart VM Service Protocol and implements it in its entirety.翻译过来DDS 协议是 VM Service 协议的扩展并且完整实现了 VM Service 协议本身。整个 DDS 协议基于 JSON-RPC 2.0 构建。因此如果一个请求对应 VM Service Protocol 中定义的 RPC如getVersion、resume、streamListenDDS 会把请求转发给 VM Service并把响应原样返回给客户端如果一个请求对应 DDS Protocol 中定义的 RPC如getStreamHistory、setClientName则由 DDS 实例直接处理。对客户端而言这一切是透明的——DDS 表现得像一个 VM Service 实例。1.2 三种通信形态DDS 同时提供通信形态获取方式说明HTTPdds.uri直接以 JSON-RPC 2.0 方式发起请求WebSocketdds.wsUri在 HTTP URI 基础上追加ws路径段并将 scheme 改为wsSSEdds.sseUri在 HTTP URI 基础上追加$debugHandler路径段并将 scheme 改为sse三种方式指向同一个 DDS 实例。在pkg/dds/lib/dds_launcher.dart中可以看到_toWebSocket与_toSse的具体构造逻辑前者在路径段末尾追加ws后者追加$debugHandler源码中常量kSseHandlerPath \$debugHandler见pkg/dds/lib/src/dds_impl.dart。二、SSE 支持面向 Web 客户端的通信通道在某些 Web 客户端场景下尤其是浏览器环境中SSEServer-Sent Events比 WebSocket 更友好或更必要。DDS 为此专门实现了 SSE handler监听/$debugHandler路径上的请求。2.1 SSE 连接流程当客户端通过 SSE 连接 DDS 时DDS 会为该连接建立一个双向的抽象通道客户端向dds.sseUri即${ddsUri}\$debugHandler发起 SSE 连接DDS 通过 SSE 事件流把 VM Service / DDS 的响应与通知推送给客户端客户端通过该连接的 sink 向上发送请求数据。值得注意的是sseUri的 scheme 为sse。在pkg/dds/test/sse_smoke_test.dart的测试代码中浏览器端连接 DDS 时会先把 scheme 替换回http因为 SSE 在 CORS 场景下不认sseschemedds.sseUri!.replace(scheme: http)。如果你从 Web 页面连接需要同样处理。2.2 官方示例SSE package:vm_servicepkg/dds/README.md给出的完整示例展示了如何用package:sse建立 DDS 连接再用package:vm_service发起请求import package:sse/sse.dart; import package:vm_service/vm_service.dart; void main() { // Establish connection with DDS using SSE. final ddsChannel SseClient(${ddsUri}\$debugHandler); // Wait for ddsChannel to be established await ddsChannel.onOpen.first; // Initialize VmService using the sink and stream from ddsChannel. final vmService VmService( ddsChannel.stream, (e) ddsChannel.sink.add(e), ); // Youre ready to query DDS and the VM service! print(await vmService.getVersion()); }这里SseClient来自package:sse它把一条 SSE 连接抽象成StreamChannelstream是服务端推来的数据流sink是客户端发送请求的通道。VmService的构造参数恰好接受这两个回调因此可以无缝对接。建立后vmService.getVersion()这样的调用会先到达 DDS再被转发到 VM Service最终把版本信息返回。2.3 与 WebSocket 方式的对比在pkg/dds/example/example.dart中展示的是 WebSocket 连接方式final dds await DartDevelopmentService.startDartDevelopmentService( remoteVmServiceUri, ); // Connect to the DDS instance and make a request using package:vm_service. final service await vmServiceConnectUri(dds.wsUri.toString()); final version await service.getVersion(); print(Service Version: $version); await dds.shutdown(); process.kill();两种方式在 API 层面殊途同归SSE 适合浏览器内客户端如 DevTools 的 Web 前端WebSocket 适合任意 Dart/非 Dart 进程。三、启动 DDS进程内 API 与独立进程 LauncherDDS 提供两套启动途径二者最终都通往同一个DartDevelopmentServiceImpl。3.1 进程内启动startDartDevelopmentService静态方法DartDevelopmentService.startDartDevelopmentService在当前进程内直接创建并启动 DDS 服务实例。其完整签名与默认值如下static FutureDartDevelopmentService startDartDevelopmentService( Uri remoteVmServiceUri, { String? appName, Uri? serviceUri, bool enableAuthCodes true, bool ipv6 false, bool enableServicePortFallback false, ListString cachedUserTags const [], // 已废弃传参不产生任何效果 DevToolsConfiguration? devToolsConfiguration, bool logRequests false, UriConverter? uriConverter, bool disableServiceOriginCheck false, })关键参数语义均来自源码 doc 注释参数默认值作用remoteVmServiceUri必填DDS 将要通信的 VM Service 地址必须为 HTTP scheme否则抛ArgumentErrorserviceUrinull决定 DDS 绑定的地址与端口必须与ipv6指定的协议族一致enableAuthCodestrue是否要求客户端提供认证码base64 字符串作为 DDS 路径的第一段默认开启ipv6false是否通过 IPv6 提供服务默认 IPv4enableServicePortFallbackfalse指定端口不可用时是否回退绑定到任意可用端口appNamenull应用短描述注册 VM Service 时作为name发送给 Dart Tooling DaemondisableServiceOriginCheckfalse是否关闭 HTTP/WebSocket 的 origin 校验DDS 实例对外暴露的地址通过以下 getter 获取未运行时返回nulluriHTTP 通信地址wsUriWebSocket 通信地址sseUriSSE 通信地址devToolsUri托管的 DevTools 实例地址若未托管则返回 nullisRunning是否正在接受请求done服务关闭时完成的 Future。3.2 独立进程启动DartDevelopmentServiceLauncherDartDevelopmentServiceLauncher.start以独立子进程方式拉起 DDS适合需要与宿主进程隔离的场景例如 Dart VM 的development-service子命令。它的参数与进程内版本大体对应额外支持serveDevTools是否由 DDS 托管 DevToolsdevToolsServerAddress将 DevTools 请求重定向到既有的 DevTools 服务器仅在serveDevTools为 true 时生效dartExecutable指定用于拉起 DDS 的 dart 可执行文件路径默认使用Platform.executable。Launcher 有一个性能相关的细节当检测到dartaotruntime与 AOT 快照dds_aot.dart.snapshot存在时即 SDK 安装环境会直接用dartaotruntime执行 AOT 快照跳过 dart CLI 的额外一跳否则回退为dart development-service ...。3.3 CLI 命令行参数独立进程模式下DDS 接受以下命令行选项定义于pkg/dds/lib/src/arg_parser.dart选项必填/默认说明--vm-service-uri必填DDS 将要连接的 VM Service URI--bind-address默认localhostDDS 绑定的地址--bind-port默认0DDS 服务的端口0 表示随机端口--disable-service-auth-codes标志关闭认证码--disable-service-origin-check标志关闭 HTTP/WebSocket origin 校验--serve-devtools标志由 DDS 托管 DevTools--devtools-server-address—重定向到既有 DevTools 服务器需配合--serve-devtools--enable-service-port-fallback标志端口被占用时回退到随机端口--google3-workspace-root隐藏设置 google3:// URI 解析的工作区根目录--app-name—应用的短描述3.4 启动失败与错误码DDS 启动/连接失败时会抛出DartDevelopmentServiceException它携带结构化错误码existingDdsInstanceError1目标 VM Service 上已存在一个 DDS 实例对应ExistingDartDevelopmentServiceException可通过其ddsUri拿到既有实例地址failedToStartError2启动期间与远端 VM Service 的连接意外终止connectionError3启动后发生连接错误。此外startDartDevelopmentService要求目标 VM Service没有其他已连接的客户端Requires the target VM service to have no other connected clients这是 DDS 独占 VM Service 连接的设计前提。四、DDS 协议核心流Streams与事件历史DDS 协议当前版本2.1见pkg/dds/dds_protocol.md继承 VM Service 协议的 JSON-RPC 2.0 约定同时引入一批只有 DDS 才有的扩展。4.1 带历史的流VM Service 协议中定义了核心流streamListen。DDS 在此基础上为以下四条流维护事件历史当客户端首次订阅这些流时DDS 会把历史事件一并回放给客户端Logging日志Stdout标准输出Stderr标准错误Extension扩展事件此外订阅Service流时DDS 会为每个已存在的 service extension 向订阅客户端发送一条ServiceRegistered事件——这对应pkg/dds/lib/src/stream_manager.dart中_buildStreamRegisteredEvent的构造逻辑。从协议版本1.4起客户端还可以通过 DDS 订阅任意名称的自定义流配合dart:developer的postEvent使用。4.2 流事件的分发实现从源码看DDS 的流机制由pkg/dds/lib/src/stream_manager.dart的StreamManager实现客户端调用streamListen后DDS 记录该客户端与流 ID 的映射VM Service 侧产生的streamNotify通知会由streamNotify(streamId, data)分发给所有订阅者。值得注意的是二进制事件Uint8List类型的数据如 CPU 采样会绕过 JSON-RPC直接通过订阅者的 WebSocket sink 转发以减少序列化开销。五、DDS 协议公开 RPC 详解DDS 支持 VM Service Protocol 的全部公开 RPC并新增以下公开 RPC。带[optional]的参数均为可选参数。5.1 客户端标识getClientName/setClientNameClientName getClientName() Success setClientName(string name)getClientName返回当前连接的 VM Service 客户端名称若从未通过setClientName设置过则返回默认名称setClientName设置当前客户端名称。name为非空字符串时更新名称name为空字符串时重置为默认名称。返回值类型ClientName包含一个string name字段。5.2 协议版本getDartDevelopmentServiceVersionVersion getDartDevelopmentServiceVersion()用于查询当前 DDS 实例所实现的 Dart Development Service Protocol 版本返回Version类型。对应源码中DartDevelopmentService.protocolVersion 2.1pkg/dds/lib/dds.dart。5.3 流历史getStreamHistoryStreamHistory getStreamHistory(string streamId)返回指定流的全部历史事件返回类型StreamHistory包含ListEvent history。仅对支持事件历史的流见上文带历史的流有效。对应的测试位于pkg/dds/test/get_stream_history_test.dart。5.4 日志历史缓冲getLogHistorySize/setLogHistorySizeSize getLogHistorySize() Success setLogHistorySize(int size)getLogHistorySize返回日志历史缓冲区的当前大小返回的Size为 0 表示日志历史已禁用setLogHistorySize设置用于缓存历史日志消息的环形缓冲区大小。size 为 0 时禁用日志历史最大 100,000 条默认 10,000 条。日志历史的具体实现位于pkg/dds/lib/src/logging_repository.dart环形缓冲区实现位于pkg/dds/lib/src/common/ring_buffer.dart。5.5 自定义事件postEventvoid postEvent(String stream, String eventKind, Map eventData)向自定义 Event 流发送事件配合dart:developer的postEvent与 1.4 起的自定义流订阅能力使用。相关测试见pkg/dds/test/post_event_custom_stream_test.dart。5.6 暂停/恢复审批机制这是 DDS 最复杂的扩展能力之一服务于多个客户端同时连接一个隔离区isolate时谁能决定恢复执行的协作问题。requirePermissionToResumeSuccess requirePermissionToResume(bool onPauseStart [optional], bool onPauseReload [optional], bool onPauseExit [optional])为客户端开启暂停后需审批才能恢复的行为可分别针对三种暂停类型独立开关onPauseStartisolate 在启动暂停后不会恢复直到客户端发送resume请求且所有需要为该暂停类型提供审批的客户端都已同意onPauseReloadisolate 在reload 后暂停时同理onPauseExitisolate 在退出暂停时同理。开启审批的客户端应当调用readyToResume表示我已完成工作可以恢复而不是直接调用resume。readyToResumeSuccess readyToResume(string isolateId)向 DDS 表示当前客户端已准备好恢复指定 isolate更新该 isolate 的审批状态当所有需要审批的客户端都已批准后恢复该 isolate若 isolate 已不存在返回 collected sentinel。requireUserPermissionToResumeSuccess requireUserPermissionToResume(bool onPauseStart [optional], bool onPauseExit [optional])通知 DDS 是否应等待resume请求来恢复启动暂停/退出暂停的 isolate。该 RPC 只应由启动目标 Dart 进程的工具调用——因为只有启动方才知道用户是否要求 isolate 在启动/退出时暂停。重要注意事项原文要点同名客户端共享恢复权限具有相同 client name 的所有客户端共享同一份恢复审批状态同名客户端中只需一个提供审批即可断开连接的影响当需要审批的客户端断开时若其他需要审批的客户端都已批准暂停的 isolate 可能恢复若没有其他客户端需要对当前暂停事件审批则只要有至少一个其他客户端尝试过resumeisolate 就会被恢复VmService.resume是强恢复resumeRPC 被视为用户发起的恢复会强制恢复 isolate从而绕过审批机制。因此依赖恢复审批的工具应使用readyToResume而非resume避免意外强恢复。DDS 在pkg/dds/lib/src/constants.dart中用位掩码表示暂停类型pauseOnStartMask 1 0、pauseOnReloadMask 1 1、pauseOnExitMask 1 2。相关测试覆盖了同名客户端、审批后再断开、强制恢复、名称变更等大量场景见pkg/dds/test/client_resume_approvals_*系列。5.7 Perfetto 时间线getPerfettoVMTimelineWithCpuSamplesPerfettoTimeline getPerfettoVMTimelineWithCpuSamples(int timeOriginMicros [optional], int timeExtentMicros [optional])与 VM Service 协议的getPerfettoVMTimeline几乎一致区别在于返回的PerfettoTimeline.trace是 Base64 编码的 Perfetto 格式 trace不仅包含指定时间范围内的所有时间线事件还包含所有 isolate 在该范围内的全部 CPU 样本。相关测试见pkg/dds/test/get_perfetto_vm_timeline_test.dart。5.8 已废弃 RPCCPU 样本缓存AvailableCachedCpuSamples getAvailableCachedCpuSamples(); CachedCpuSamples getCachedCpuSamples(string isolateId, string userTag);这两个 RPC 从协议版本 2.1 起已废弃getAvailableCachedCpuSamples永远返回一个cacheNames为空数组的AvailableCachedCpuSamplesgetCachedCpuSamples永远返回占位值placeholder values。对应的cachedUserTags参数在启动 API 中同样被标记为Deprecated传参不产生任何效果。类型定义仍保留在协议文档中供兼容。六、请求路由的底层实现转发与直处理理解 DDS既像 VM Service、又不是 VM Service的关键在于pkg/dds/lib/src/dds_impl.dart中的请求路由逻辑。从源码结构可以推断出如下路由策略相关注释见 dds_impl.dart认证与校验阶段DDS 先校验客户端请求头包括认证码与 origin若开启DDS 专属 RPC对应 DDS Protocol 的 RPC如getStreamHistory、setClientName、readyToResume等由 DDS 自身的 handler 直接处理DevTools 路由DevTools 相关的 HTTP 请求被路由到 DevTools 服务无论由 DDS 托管还是重定向到外部 DevTools 服务器setExternalDevToolsUri用于注册外部实例VM Service 转发其余未处理的 HTTP 请求通过shelf_proxy原样转发给远端 VM Service并把响应返回。正是因为这一层透传代理客户端几乎无需感知 DDS 的存在而 DDS 的扩展能力流历史、客户端命名、恢复审批则插在代理路径上为整个工具链提供统一的增值层。七、测试与验证如何确认 DDS 正常工作仓库为 DDS 提供了完整的测试集pkg/dds/test可作为理解与验证行为的权威参考sse_smoke_test.dart在浏览器headless Chrome WebDriver中通过 SSE 连接 DDS验证getVersion返回合法版本同时覆盖认证码开启/关闭两种模式smoke_test.dart与smoke.dart启动一个只打印Hello world!的最小 Dart 进程再对其 VM Service 启动 DDS做基本连通性验证launcher_smoke_test.dart验证独立进程 Launcher 的启动链路client_resume_approvals_*系列全面覆盖恢复审批机制的协作行为dds_exception_parsing_test.dart验证错误码与异常 JSON 的解析。快速验证脚本进程内启动 WebSocket参考pkg/dds/example/example.dart的流程一个最小可运行的验证步骤为启动一个带 VM Service 的 Dart 进程如dart --enable-vm-service test.dart取得remoteVmServiceUri调用DartDevelopmentService.startDartDevelopmentService(remoteVmServiceUri)用vmServiceConnectUri(dds.wsUri.toString())建立VmService连接调用getVersion()应返回 VM Service 与 DDS 的版本信息最后调用dds.shutdown()优雅关闭。八、实践要点小结连接形态选择进程内工具建议直接走 WebSocketwsUri浏览器内 Web 客户端如 DevTools 前端建议走 SSEsseUri并注意把 scheme 替换为http以规避 CORS 对ssescheme 的限制认证码默认开启enableAuthCodes默认true认证码是 base64 字符串并作为 DDS 路径的第一段生产环境不建议关闭端口回退enableServicePortFallback可在指定端口被占用时自动回退适合动态端口场景恢复审批纪律多客户端协作调试时遵循审批机制的客户端应使用readyToResume而不是resume否则会触发强恢复流历史有上限日志历史默认 10,000 条、最大 100,000 条可通过setLogHistorySize调整或置 0 禁用依赖与版本dds包当前版本为 5.5.0-wip要求 Dart SDK^3.5.0协议版本 2.1详细依赖见pkg/dds/pubspec.yaml。深入阅读建议协议全貌见pkg/dds/dds_protocol.md启动 API 见pkg/dds/lib/dds.dart与pkg/dds/lib/dds_launcher.dart请求路由与 SSE handler 见pkg/dds/lib/src/dds_impl.dart流分发见pkg/dds/lib/src/stream_manager.dart命令行选项见pkg/dds/lib/src/arg_parser.dart。赞分享编程语言编译器语言运行时标准库开发工具【免费下载链接】sdkThe Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.项目地址https://gitcode.com/gh_mirrors/sdk1/sdk点击查看免费下载相关推荐在 aisuite 中接入 Cohere从 API Key 配置到首个 Chat Completion 的完整实战在 aisuite 中接入 Cohere从 API Key 配置到首个 Chat Completion 的完整实战 本篇技术指南以仓库 guides/cohe编程语言编译器语言运行时标准库开发工具PDF 补丁丁PDFPatcher免费开源的 PDF 修理箱PDF 补丁丁PDFPatcher免费开源的 PDF 修理箱 一份 300 页的招标文件翻到第 200 页想回看前面的条款书签栏空空如也只能一页页往编程语言编译器语言运行时标准库开发工具mcp-playwright SSE传输协议实时通信技术深度解析mcp playwright SSE传输协议实时通信技术深度解析 mcp playwright 的 SSEServer Sent Events传输协议是现MCP 服务浏览器控制AI 应用上一篇5分钟终极指南Brigadier一键搞定Mac Boot Camp驱动完整方案下一篇BaiduPCS-Web终极指南如何构建高速百度网盘Web客户端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号