- 存储
- 网络
- 通信
【免费下载链接】js-ipfs
IPFS implementation in JavaScript
导读
Swarm(对等连接集群)是 js-ipfs 节点网络层的心脏:它负责维护节点与网络中其他对等节点的连接关系,提供"查看已知地址、主动建连、主动断开、查看本机监听地址、查看已连接邻居"这五大能力。本文以 docs/core-api/SWARM.md 为核心骨架,结合 js-ipfs 仓库内 ipfs-core 的实现、libp2p 的底层封装 与 接口测试套件 等源码证据,为你讲透 Swarm API 的每个方法、每个参数、每个返回字段,并给出 JS 调用、CLI 命令、HTTP 网关三种使用姿势。读完本文,你将能够熟练地让 js-ipfs 节点按需连接/断开对等节点、排查连接状态、定位本机监听地址,并理解其背后的 libp2p 机制。
从全局看懂 Swarm API:五个方法一张表
Swarm API 挂在ipfs.swarm命名空间下,共五个方法,覆盖"连接建立、连接拆除、邻居查询、地址查询"四个维度:
| 方法 | 作用 | 对应实现文件 |
|---|---|---|
ipfs.swarm.addrs() | 列出本节点已知的、每个已连接对等节点的全部地址 | addrs.js |
ipfs.swarm.connect(addr) | 向给定地址/PeerId 打开一条连接 | connect.js |
ipfs.swarm.disconnect(addr) | 关闭与给定地址/PeerId 的连接 | disconnect.js |
ipfs.swarm.localAddrs() | 返回本节点正在监听的本地地址 | local-addrs.js |
ipfs.swarm.peers() | 列出本节点当前保有连接的对等节点 | peers.js |
在 js-ipfs 的代码组织上,这五个方法由 SwarmAPI 类 统一装配,每个方法都接收一个{ network }依赖并从中取出 libp2p 实例来工作。它们的 TypeScript 类型签名集中在 ipfs-core-types/src/swarm/index.ts,是该 API 的"标准答案",后续每节的返回字段都以它为准。
使用前提:Swarm 是一组"在线" API。CLI 层的命令会在 daemon 未运行时明确报错(This command must be run in online mode),HTTP 网关的对应端点同样依赖 daemon 进程。你可以在所有 js-ipfs 发行形态(ipfs-core 进程内实例、ipfs-http-client 远程客户端、CLI、HTTP RPC 网关)中使用同一套方法语义。
通用选项:timeout 与 signal 的底层实现
除peers()有专属选项外,其余四个方法共享同一组通用选项:
| Name | Type | Default | Description |
|---|---|---|---|
| timeout | Number | undefined | 以毫秒为单位的超时时间 |
| signal | [AbortSignal][] | undefined | 可用于取消本调用引发的任何长时间运行的请求 |
这两个选项不是摆设,它们在 js-ipfs 中通过 withTimeoutOption 包装器实现:每个 Swarm 方法(如createAddrs、createConnect、createPeers)的返回值都会经过withTimeoutOption()包装。其内部逻辑是:
- 未传入
timeout时,直接透传执行; - 传入
timeout时,创建一个TimeoutController,并把你的signal与超时信号用anySignal合并——这意味着外部 abort 与内部超时任一发生都会中止底层 libp2p 调用; - 超时后会抛出
TimeoutError(定义于 errors.js),并清理定时器与迭代器资源。
因此,在生产代码中给 Swarm 调用加timeout是防止 dial(拨号)这类可能长时间阻塞的操作卡死主流程的最简手段。
ipfs.swarm.addrs([options]):查看每个邻居的已知地址
语义与返回
List of known addresses of each peer connected.
返回已知的、每个已连接对等节点的地址列表:
| 返回类型 | 说明 |
|---|---|
Promise<Array<{ id: String, addrs: Multiaddr[] }>> | 每个元素含对等节点的 ID 字符串id,以及该节点的一组Multiaddr地址addrs |
底层实现
看 addrs.js 的实现:它从network.use(options)取出 libp2p,然后遍历libp2p.peerStore(对等节点信息库),把每个 peer 的id与其addresses中记录的multiaddr收集成数组返回。也就是说,addrs 返回的是"本节点 Peer Store 里记录的地址",而非实时拨号探测的结果,这是理解该方法数据来源的关键。
示例
const peerInfos = await ipfs.swarm.addrs() peerInfos.forEach(info => { console.log(info.id) /* QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt */ info.addrs.forEach(addr => console.log(addr.toString())) /* /ip4/147.75.94.115/udp/4001/quic /ip6/2604:1380:3000:1f00::1/udp/4001/quic /dnsaddr/bootstrap.libp2p.io /ip6/2604:1380:3000:1f00::1/tcp/4001 /ip4/147.75.94.115/tcp/4001 */ })从输出可以看到,一个对等节点往往同时暴露 IPv4、IPv6、TCP、QUIC、DNS 解析型等多种 Multiaddr,js-ipfs 会原样返回全部已知条目。接口测试套件 addrs.js 断言了每个返回项的id非空、addrs为数组且每个元素都是合法的Multiaddr,你可以照此校验自己的实现。
ipfs.swarm.connect(addr, [options]):主动拨号建连
语义与返回
Open a connection to a given address.
| 参数 | 类型 | 说明 |
|---|---|---|
| addr | Multiaddr或PeerId | 要连接的对等节点地址或 Peer ID |
| 返回类型 | 说明 |
|---|---|
Promise<void> | 建连成功后 resolve;失败则抛错 |
底层实现
看 connect.js:核心只有一行 ——await libp2p.dial(multiaddrOrPeerId, options)。也就是说 connect 是 libp2pdial的薄封装。dial 会经历"传输握手 → 加密协商(默认 noise,见 libp2p.js)→ 多路复用(默认 mplex)→ identify 交换"的完整建连流程,之后该连接才会出现在peers()的返回中。在 HTTP 网关端(swarm.js)还做了特别处理:连接建立后不再转发客户端断开引发的 abort,以确保 identify 过程能完整走完。
示例
await ipfs.swarm.connect(addr)其中addr可以是:
// 1. 完整 Multiaddr(含 /p2p/ 后缀标识对端 PeerId) const ma = multiaddr('/ip4/127.0.0.1/tcp/4002/p2p/Qm...') // 2. 仅 PeerId(js-ipfs 会借助 DHT/对等路由完成寻址与拨号) await ipfs.swarm.connect(peerId)connect 与 disconnect 的接口测试(connect.js)给出了可复现的验证流程:两个节点 A/B 启动后,先断言 B 不在 A 的peers()列表里,A 调用connect(B 的地址)后,再断言 B 出现在peers()中——这正是"连接是否真的建立"的判别标准。
ipfs.swarm.disconnect(addr, [options]):主动断开连接
语义与返回
Close a connection on a given address.
| 参数 | 类型 | 说明 |
|---|---|---|
| addr | Multiaddr或PeerId | 要断开的对等节点地址或 Peer ID |
| 返回类型 | 说明 |
|---|---|
Promise<void> | 断开成功后 resolve;否则抛错 |
底层实现
看 disconnect.js:核心是await libp2p.hangUp(addr)。hangUp会关闭与该对端的所有连接并清理相关状态。对应测试 disconnect.js 验证了"先 connect、再 disconnect、最后peers()回到空列表"的完整闭环。
示例
await ipfs.swarm.disconnect(addr)ipfs.swarm.localAddrs([options]):本机监听地址
语义与返回
Local addresses this node is listening on.
| 返回类型 | 说明 |
|---|---|
Promise<Multiaddr[]> | 本节点正在监听的本地地址数组 |
底层实现
看 local-addrs.js:直接返回libp2p.getMultiaddrs()。监听地址来自节点启动时从配置读取的Addresses.Swarm列表——默认配置(见 ipfs-core-config/src/config.js)为'/ip4/0.0.0.0/tcp/4002'(TCP 监听)与'/ip4/127.0.0.1/tcp/4003/ws'(WebSocket 监听)。在 network.js 中,这些 Multiaddr 会经过readAddrs处理:若地址本身带有对端 PeerId(如经信令服务器的中转地址),会追加/替换为本节点自己的 PeerId 后再交给 libp2p 监听。
示例
const multiAddrs = await ipfs.swarm.localAddrs() console.log(multiAddrs)测试 local-addrs.js 会断言返回的是非空数组(浏览器 WebWorker 等无网络能力的环境除外)。你可以用这个方法快速确认 daemon 是否真的在预期端口上监听。
ipfs.swarm.peers([options]):列出当前连接的对等节点
专属选项
| Name | Type | Default | Description |
|---|---|---|---|
| direction | boolean | false | 为 true 时返回连接方向信息 |
| streams | boolean | false | 为 true 时返回打开的 muxed 流信息 |
| verbose | boolean | false | 为 true 时返回全部附加信息 |
| latency | boolean | false | 为 true 时返回延迟信息 |
| timeout | Number | undefined | 毫秒超时 |
| signal | AbortSignal | undefined | 取消长时间运行的请求 |
返回结构
返回Promise<Object[]>,每个元素为:
addr: Multiaddrpeer: Stringlatency: String— 仅当verbose: true时返回muxer: String— 对端使用的流多路复用器类型streams: string[]— 仅当verbose: true时返回,当前打开的流列表direction: number— 入站(inbound)或出站(outbound)连接
若为某个对端构建对象时出错,该元素会退化为仅含:
error: Error— 发生的错误rawPeerInfo: Object— 该对端的原始数据
其余属性可能为undefined。在类型定义 swarm/index.ts 中,direction的合法值是'inbound' | 'outbound'。
底层实现与去重逻辑
看 peers.js 的实现,有两个值得注意的细节:
- 默认(非 verbose)模式下用 Map 去重:遍历
libp2p.getConnections()时以remotePeer.toString()为键存入 Map,再取values()。这意味着同一个对端即使有多条连接、多个地址,也只会出现一次。 - verbose 模式下按连接逐条返回:
direction取自connection.stat.direction,muxer取自connection.stat.multiplexer,latency当前实现固定为'n/a',streams为空数组(源码中以 TODO 标注待从 libp2p 获取)。
对应测试 peers.js 明确断言了这些行为:默认模式下每个 peer 必须有addr与peer且不能有latency;verbose 模式下latency必须匹配n/a或3ms、3µs、3s这类时长格式;还专门写了"多地址也只出现一次"的去重测试。
示例
const peerInfos = await ipfs.swarm.peers() console.log(peerInfos) // 需要方向与更多细节时: const detailed = await ipfs.swarm.peers({ verbose: true, direction: true })三种调用姿势:JS API、CLI 命令、HTTP 网关
进程内 JS API(ipfs-core)
以上示例即为 ipfs-core 进程内实例的用法,五个方法由 SwarmAPI 直接挂在ipfs.swarm上。这是嵌入式使用 js-ipfs(如自建节点应用、测试环境)的标准姿势。
CLI 命令(ipfs-cli)
CLI 层(ipfs-cli/src/commands/swarm)把五个方法映射为五个子命令,均要求先运行ipfs daemon:
# 列出当前连接的对等节点 ipfs swarm peers # 列出已知的对等节点地址 ipfs swarm addrs # 仅列出本机监听地址 ipfs swarm addrs local # 连接指定地址 ipfs swarm connect /ip4/127.0.0.1/tcp/4002/p2p/Qm... # 断开指定地址 ipfs swarm disconnect /ip4/127.0.0.1/tcp/4002/p2p/Qm...每个命令都支持--timeout(内部经parse-duration解析,如--timeout 30s)。swarm peers的输出会对地址做mafmt校验,若对端地址缺少/ipfs/后缀,会补上再打印(见 peers.js);swarm addrs则会把每个 peer 的地址缩进打印在其 ID 与地址数量之下(见 addrs.js)。
HTTP RPC 网关(ipfs-http-server / ipfs-http-client)
HTTP 服务器在 routes/swarm.js 中注册了五个 POST 端点:
| 端点 | 对应方法 | 请求参数 |
|---|---|---|
/api/v0/swarm/peers | peers | verbose、direction、timeout(支持v简写为 verbose) |
/api/v0/swarm/addrs | addrs | timeout |
/api/v0/swarm/addrs/local | localAddrs | timeout |
/api/v0/swarm/connect | connect | arg(Multiaddr 或 PeerId,必填) |
/api/v0/swarm/disconnect | disconnect | arg(同上) |
connect/disconnect 的arg支持两种形态:以/开头按 Multiaddr 解析,否则按 PeerId 字符串解析(见 resources/swarm.js)。
而 JS 侧通过 ipfs-http-client 调用时,使用完全一致的ipfs.swarm.*方法名即可——swarm 目录 下的五个文件把本地方法调用转换为对上述端点的 POST 请求,并把 JSON 响应还原为Multiaddr、PeerId等对象(例如peers响应中的Direction数字0/1会被映射为'inbound'/'outbound'字符串,见 peers.js)。
实战:用 Swarm API 排查与诊断连接问题
结合以上内容,可以总结一套可落地的诊断流程:
- 确认监听正常:先跑
ipfs.swarm.localAddrs()(或ipfs swarm addrs local),核对返回地址是否包含预期的Addresses.Swarm条目;若为空,检查配置与网络环境。 - 确认邻居在册:跑
ipfs.swarm.peers(),看目标节点是否出现在列表中。注意默认模式会按 PeerId 去重,不要因为"地址数多"误判连接数。 - 确认地址记录:跑
ipfs.swarm.addrs(),查看 Peer Store 里记录的对端地址,判断是否因地址缺失/过期导致拨号失败。 - 主动建连验证:
ipfs.swarm.connect(multiaddr)后立刻再查peers(),这是最直接的连通性验证——接口测试套件正是用这一模式来断言连接成功的。 - 需要明细时开 verbose:
peers({ verbose: true, direction: true })可看到连接方向与 muxer 类型,用于区分入站/出站连接、判断多路复用协议是否协商成功。
注意addrs()与peers()的数据语义不同:前者来自 Peer Store(本地已知信息,可能陈旧),后者来自实时连接表(getConnections()),两者结合才能看清"知道谁"与"连上了谁"的全貌。
深入阅读
- 接口标准与返回类型:ipfs-core-types/src/swarm/index.ts
- 核心实现:packages/ipfs-core/src/components/swarm
- 跨实现接口测试:packages/interface-ipfs-core/src/swarm
- 底层 libp2p 组装:libp2p.js、network.js
- 默认监听地址与 Bootstrap 配置:ipfs-core-config/src/config.js
- HTTP 网关实现:routes/swarm.js、resources/swarm.js
- HTTP 客户端实现:packages/ipfs-http-client/src/swarm
- CLI 命令实现:packages/ipfs-cli/src/commands/swarm
- 存储
- 网络
- 通信
【免费下载链接】js-ipfs
IPFS implementation in JavaScript
相关推荐
js-ipfs 客户端库 ipfs-client 使用指南:HTTP 与 gRPC 双通道连接本地 IPFS 节点
js ipfs 客户端库 ipfs client 使用指南:HTTP 与 gRPC 双通道连接本地 IPFS 节点 ipfs client 是 js IPFS
存储网络通信OrbitDB 节点互联实战:基于 js-libp2p 的 Peer 连接配置全指南
OrbitDB 节点互联实战:基于 js libp2p 的 Peer 连接配置全指南 OrbitDB 的节点之间通过 js libp2p 相互连接,本文以官方文
数据库分布式数据库掌握 React Flow 动态节点连接:从状态管理到高级交互
掌握 React Flow 动态节点连接:从状态管理到高级交互 你是否在构建流程图应用时遇到过节点连接状态混乱、动态更新异常或性能瓶颈?本文将系统讲解 Reac
前端UI组件图表库
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考