go-libp2p 入门 example

cc14514 · · 6796 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Install go-libp2p

go get -u -d github.com/libp2p/go-libp2p/...
cd $GOPATH/src/github.com/libp2p/go-libp2p
make
make deps

官网给出了安装说明:

go get 中 -u 表示下载最新版的依赖,-d 表示只下载不安装,当然你需要先安装 golang 才能使用 go get ,这里推荐安装 1.10.x 版本

golang安装包 : https://studygolang.com/dl

make 时需要下载 gx 组件,如果想直接用 make 来下载最好还是先“科学上网”,如果直接在 github 上下载安装 gx 则无需担心 “科学上网问题”

make deps 是要下载全部依赖了,这里会用 gx 来完成下载,第一次用时你会发现他要到 ipfs.io 去 get 依赖包,但是即便“科学上网”了也还是无法访问,其实只要在本地先启动一个 ipfs 节点就可以了,他会优先在本地的 ipfs 节点获取资源

IPFS 的下载和安装 : https://ipfs.io/docs/install/

启动命令: ipfs daemon

然后再去 make deps 经过漫长的等待,即可完成依赖的安装

很多小伙伴是不是都在这一步放弃了 go-libp2p 呀?其实我也挺讨厌这个 gx 的,不如 govendor 用着舒服,不幸的是想继续探索 go-libp2p 你就必须要掌握 gx 的用法,并且要去习惯使用 gx

gx教程:https://github.com/whyrusleeping/gx

安装还是比较容易的,一定要粗略的看一遍说明书再去看代码和例子,否则很难发现它的美

libp2p 说明书: https://github.com/libp2p/specs

Example

PingService

使用 libp2p 做服务是我们学习的目的,通过 PingService 来入门是个不错的选择,简单看一下 PingService 的代码,你会发现实现一个服务非常简单, host.Host 接口是核心

PingService : http://github.com/libp2p/go-libp2p/p2p/protocol/ping/ping.go

......
const ID = "/ipfs/ping/1.0.0"

type PingService struct {
    Host host.Host
}

func NewPingService(h host.Host) *PingService {
    ps := &PingService{h}
    h.SetStreamHandler(ID, ps.PingHandler)
    return ps
}

func (p *PingService) PingHandler(s inet.Stream) {
    ......
}
func (ps *PingService) Ping(ctx context.Context, p peer.ID) (<-chan time.Duration, error) {
    s, err := ps.Host.NewStream(ctx, p, ID)
    ......
}
......

这个代码片段演示如何通过 host.Host 接口构建一个服务,Host 接口描述如下:

Host is an object participating in a p2p network, which implements protocols or provides services. It handles requests like a Server, and issues requests like a Client. It is called Host because it is both Server and Client (and Peer may be confusing).

在文章的结尾贴出了 Host 接口的代码,这个服务主要使用下面这两个方法

  • SetStreamHandler(pid protocol.ID, handler inet.StreamHandler)
    首先通过 Host.SetStreamHandler 来为 "/ipfs/ping/1.0.0" 协议指定 callback 方法,这里指定了 PingHandler 方法,参数中的 inet.Stream 接口对 io 接口做了扩展,这里要做的就是当请求到来时对 s 的输入流做读操作

  • NewStream(ctx context.Context, p peer.ID, pids ...protocol.ID) (inet.Stream, error)
    在 Ping 方法被调用时首先通过 NewStream 打开了一个流,在 p2p 网络中打开流都是有目标的,这个目标就是 peer.ID ,因为这个 peer 上可能会注册很多服务,所以也要指明服务ID,就是参数中的 protocol.ID ,剩下的工作就是向 s 的输出流中写入数据包了。

TODO : 调用 PingService

感觉上调用一个服务比编写一个服务复杂的多,
首先NewHost就是一个非常复杂的操作,参数中的 Network 接口我们用 Swarm 来填充,那么 swarm 又是什么呢?它在这里是 Network 接口的一个实现,
Host 接口有两个实现,我们用 BasicHost 来实例化 Host 接口.

BasicHost: (github.com/libp2p/go-libp2p/p2p/host/basic/basic_host.go)

第二个参数 net 是 Network 接口类型,我们用 swarm 对象来填充即可得到一个 Host 接口的实现对象
// NewHost constructs a new *BasicHost and activates it by attaching its stream and connection handlers to the given [inet.Network](http://inet.Network).
func NewHost(ctx context.Context, net inet.Network, opts *HostOpts) (*BasicHost, error) {
......

go-libp2p-host 接口

// Host is an object participating in a p2p network, which implements protocols or provides services. It handles requests like a Server, and issues requests like a Client. It is called Host because it is both Server and Client (and Peer may be confusing).

type Host interface {

   // ID returns the (local) [peer.ID](http://peer.ID) associated with this Host

   ID() peer.ID

   // Peerstore returns the Host's repository of Peer Addresses and Keys.

   Peerstore() pstore.Peerstore

   // Returns the listen addresses of the Host

   Addrs() []ma.Multiaddr

   // Networks returns the Network interface of the Host

   Network() inet.Network

   // Mux returns the Mux multiplexing incoming streams to protocol handlers

   Mux() *msmux.MultistreamMuxer

   // Connect ensures there is a connection between this host and the peer with given [peer.ID](http://peer.ID). Connect will absorb the addresses in pi into its internal peerstore. If there is not an active connection, Connect will issue a h.Network.Dial, and block until a connection is open, or an error is returned. 

   // TODO: Relay + NAT.

   Connect(ctx context.Context, pi pstore.PeerInfo) error

   // SetStreamHandler sets the protocol handler on the Host's Mux.

   // This is equivalent to:

   //   host.Mux().SetHandler(proto, handler)

   // (Threadsafe)

   SetStreamHandler(pid protocol.ID, handler inet.StreamHandler)

   // SetStreamHandlerMatch sets the protocol handler on the Host's Mux

   // using a matching function for protocol selection.

   SetStreamHandlerMatch(protocol.ID, func(string) bool, inet.StreamHandler)

   // RemoveStreamHandler removes a handler on the mux that was set by

   // SetStreamHandler

   RemoveStreamHandler(pid protocol.ID)

   // NewStream opens a new stream to given peer p, and writes a p2p/protocol

   // header with given [protocol.ID](http://protocol.ID). If there is no connection to p, attempts

   // to create one. If ProtocolID is "", writes no header.

   // (Threadsafe)

   NewStream(ctx context.Context, p peer.ID, pids ...protocol.ID) (inet.Stream, error)

   // Close shuts down the host, its Network, and services.

   Close() error

   // ConnManager returns this hosts connection manager

   ConnManager() ifconnmgr.ConnManager

}

go-libp2p-net 中的 Network 接口

// Network is the interface used to connect to the outside world. It dials and listens for connections. it uses a Swarm to pool connnections (see swarm pkg, and peerstream.Swarm). Connections are encrypted with a TLS-like protocol.

type Network interface {

   Dialer

   io.Closer

   // SetStreamHandler sets the handler for new streams opened by the remote side. This operation is threadsafe.

   SetStreamHandler(StreamHandler)

   // SetConnHandler sets the handler for new connections opened by the remote side. This operation is threadsafe.

   SetConnHandler(ConnHandler)

   // NewStream returns a new stream to given peer p. If there is no connection to p, attempts to create one.

   NewStream(context.Context, peer.ID) (Stream, error)

   // Listen tells the network to start listening on given multiaddrs.

   Listen(...ma.Multiaddr) error

   // ListenAddresses returns a list of addresses at which this network listens.

   ListenAddresses() []ma.Multiaddr

   // InterfaceListenAddresses returns a list of addresses at which this network listens. It expands "any interface" addresses (/ip4/0.0.0.0, /ip6/::) to use the known local interfaces.

   InterfaceListenAddresses() ([]ma.Multiaddr, error)

   // Process returns the network's Process

   Process() goprocess.Process

}

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:cc14514

查看原文:go-libp2p 入门 example

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

6796 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传