第28章 【IPFS一问一答】解析IPFS Multiformat之Multiaddr

28 【IPFS一问一答】解析IPFS Multiformat之Multiaddr

Multiaddr是自我描述的网络地址。它很好的改进了目前的网络地址格式,旨在使网络成为未来的证明,可以组合和高效。

目前的寻址方案存在许多问题:

Multiaddr改进了这些问题,它的特性是:

来看一下两者的结构事例:

普通标示:

127.0.0.1:9090   # ip4. is this TCP? or UDP? or something else?
[::1]:3217       # ip6. is this TCP? or UDP? or something else?

http://127.0.0.1/baz.jpg
http://foo.com/bar/baz.jpg
//foo.com:1234
 # use DNS, to resolve to either ip4 or ip6, but definitely use
 # tcp after. or maybe quic... >.<
 # these default to TCP port :80.

而用multiaddr方法标示:

/ip4/127.0.0.1/udp/9090/quic
/ip6/::1/tcp/3217
/ip4/127.0.0.1/tcp/80/http/baz.jpg
/dns4/foo.com/tcp/80/http/bar/baz.jpg
/dns6/foo.com/tcp/443/https

使用multiaddr后,表达的更清晰,而且格式上看着更人性化,可读性高了。

28.1 multiaddr格式

Multiaddr 采用 递归TLV(type+length+value)的格式进行编码,它有两种形式:

人类友好格式定义如下:

(/<addr-protocol-str-code>/<addr-value>)+

机器友好的格式定义如下:

(<addr-protocol-code><addr-value>)+

28.2 multiaddr安装并使用

我们采用 Golang 来使用 multiaddr。

安装 multiaddr

go get github.com/multiformats/go-multiaddr

代码:

package main

import (
    "fmt"

    ma "github.com/multiformats/go-multiaddr"
)

func main() {
    // construct from a string (err signals parse failure)
    m1, err := ma.NewMultiaddr("/ip4/127.0.0.1/udp/1234")
    if err != nil {
        panic(err)
    }
    // construct from bytes (err signals parse failure)
    m2, err := ma.NewMultiaddrBytes(m1.Bytes())
    if err != nil {
        panic(err)
    }

    // true
    fmt.Println(m2.Equal(m1))
    fmt.Println(m1.Protocols())
    m3, err := ma.NewMultiaddr("/sctp/5678")
    if err != nil {
        panic(err)
    }
    fmt.Println(m1.Encapsulate(m3))
    m4, err := ma.NewMultiaddr("/udp/1234")
    if err != nil {
        panic(err)
    }
    fmt.Println(m1.Decapsulate(m4))
}

测试:

> go run multiaddr.go
true
[{ip4 4 [4] 32 false {0x4cd930 0x4cdd00 <nil>}} {udp 273 [142 2] 16 false {0x4cdd70 0x4cdf80 <nil>}}]
/ip4/127.0.0.1/udp/1234/sctp/5678
/ip4/127.0.0.1