Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
go-libp2p
Commits
ecc1c897
Commit
ecc1c897
authored
8 years ago
by
Jeromy Johnson
Committed by
GitHub
8 years ago
Browse files
Options
Download
Plain Diff
Merge pull request #152 from libp2p/doc/improveexamples
Improve echo example
parents
405d49a9
7c5d076d
master
2018-Q4-OKR
docs-improvements
feat/p2p-multiaddr
feat/pnet/working3
feat/protobuf
feat/relay-integrate
feat/udp
feature/standardize-readme
fix/473
fix/no-custom-field
fix/reset-ping-stream
fix/revert-correct-external-addr
gx/update-jccl6u
gx/update-nza0mn
jenkinsfile
kevina/fix-go-vet
multistream-ping
punching
revert-276-update-go-detect-race
v6.0.23
v6.0.22
v6.0.21
v6.0.20
v6.0.19
v6.0.18
v6.0.17
v6.0.16
v6.0.15
v6.0.14
v6.0.13
v6.0.12
v6.0.11
v6.0.10
v6.0.9
v6.0.8
v6.0.7
v6.0.6
v6.0.5
v6.0.4
v6.0.3
v6.0.2
v6.0.1
v6.0.0
v5.0.21
v5.0.20
v5.0.19
v5.0.18
v5.0.17
v5.0.16
v5.0.15
v5.0.14
v5.0.13
v5.0.12
v5.0.11
v5.0.10
v5.0.9
v5.0.8
v5.0.7
v5.0.6
v5.0.5
v5.0.4
v5.0.3
v5.0.2
v5.0.1
v5.0.0
v4.5.5
v4.5.4
v4.5.3
v4.5.2
v4.5.1
v4.5.0
v4.4.5
v4.4.4
v4.4.3
v4.4.2
v4.4.1
v4.4.0
v4.3.12
v4.3.11
v4.3.10
v4.3.9
v4.3.8
v4.3.7
v4.3.6
v4.3.5
v4.3.4
v4.3.3
v4.3.2
v4.3.1
v4.3.0
v4.2.0
v4.1.0
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
examples/echo/README.md
+72
-19
examples/echo/README.md
examples/echo/main.go
+21
-17
examples/echo/main.go
with
93 additions
and
36 deletions
+93
-36
examples/echo/README.md
View file @
ecc1c897
# Echo client/server with libp2p
This example can be started in either listen mode (server), or dial mode (client).
This is an example that quickly shows how to use the
`go-libp2p`
stack,
including Host/Basichost, Network/Swarm, Streams, Peerstores and
Multiaddresses.
In listen mode, it will sit and wait for incoming connections on
the
`/echo/1.0.0`
protocol. Whenever it receives a stream, it will
write whatever message it received, and close the stream.
This example can be started in either listen mode, or dial mode.
In dial mode, it will connect to the target peer on the given address.
It then opens a stream, writes a short message on the same protocol,
and print whatever reply it receives.
In listen mode, it will sit and wait for incoming connections on the
`/echo/1.0.0`
protocol. Whenever it receives a stream, it will write the
message "Hello, world!" over the stream and close it.
In dial mode, the node will start up, connect to the given address, open a
stream to the target peer, and read a message on the protocol
`/echo/1.0.0`
.
## Build
From
`go-libp2p`
base folder:
```
> make deps
> go build ./examples/hosts
...
...
@@ -22,20 +27,68 @@ and print whatever reply it receives.
In one terminal:
```
> ./hosts -l 4737
2016/11/06 04:37:00 I am /ip4/127.0.0.1/tcp/4737/ipfs/QmXzbaXtBw6mU29WoeYrCtcRLVbT8asWCcEFVuDy4w6pdq
2016/11/06 04:37:00 listening for connections
2016/11/06 04:37:01 got a new stream
2016/11/06 04:37:01 read request: "Hello, world!"
> ./hosts -l 1235
2016/11/10 10:45:37 I am /ip4/127.0.0.1/tcp/1234/ipfs/QmNtX1cvrm2K6mQmMEaMxAuB4rTexhd87vpYVot4sEZzxc
2016/11/10 10:45:37 listening for connections
```
In another, copy the address printed by the listener and do:
The listener libp2p host will print its
`Multiaddress`
, which indicates how it
can be reached (ip4+tcp) and its randomly generated ID (
`QmNtX1cv...`
)
Now, launch another node that talks to the listener:
```
> ./hosts -d /ip4/127.0.0.1/tcp/4737/ipfs/QmXzbaXtBw6mU29WoeYrCtcRLVbT8asWCcEFVuDy4w6pdq
2016/11/06 04:37:01 I am /ip4/127.0.0.1/tcp/0/ipfs/QmeMNYMmkgoyd8M7y925r4yVVDjKtiYtU4rNCyj7wDWzk1
2016/11/06 04:37:01 connecting to target
2016/11/06 04:37:01 opening stream
2016/11/06 04:37:01 read reply: "Hello, world!"
>
> ./hosts -d /ip4/127.0.0.1/tcp/1234/ipfs/QmNtX1cvrm2K6mQmMEaMxAuB4rTexhd87vpYVot4sEZzxc -l 1236
```
The new node with send the message
`Hello, world!`
to the
listener, which will in turn echo it over the stream and close it. The
listener logs the message, and the sender logs the response.
## Details
The
`makeBasicHost()`
function creates a
[
go-libp2p-basichost
](
https://godoc.org/github.com/libp2p/go-libp2p/p2p/host/basic
)
object.
`basichost`
objects wrap
[
go-libp2 swarms
](
https://godoc.org/github.com/libp2p/go-libp2p-swarm#Swarm
)
and should be used preferentially. A
[
go-libp2p-swarm Network
](
https://godoc.org/github.com/libp2p/go-libp2p-swarm#Network
)
is a
`swarm`
which complies to the
[
go-libp2p-net Network interface
](
https://godoc.org/github.com/libp2p/go-libp2p-net#Network
)
and takes care of maintaining streams, connections, multiplexing different
protocols on them, handling incoming connections etc.
In order to create the swarm (and a
`basichost`
), the example needs:
*
An
[
ipfs-procotol ID
](
https://godoc.org/github.com/libp2p/go-libp2p-peer#ID
)
like
`QmNtX1cvrm2K6mQmMEaMxAuB4rTexhd87vpYVot4sEZzxc`
. The example
autogenerates this on every run. An optional key-pair to secure
communications can be added to it. The example autogenerates them when
using
`-secio`
.
*
A
[
Multiaddress
](
https://godoc.org/github.com/multiformats/go-multiaddr
)
,
which indicates how to reach this peer. There can be several of them
(using different protocols or locations for example). Example:
`/ip4/127.0.0.1/tcp/1234`
.
*
A
[
go-libp2p-peerstore
](
https://godoc.org/github.com/libp2p/go-libp2p-peerstore
)
,
which is used as a address book which matches node IDs to the
multiaddresses through which they can be contacted. This peerstore gets
autopopulated when manually opening a connection (with
[
`Connect()`
](
https://godoc.org/github.com/libp2p/go-libp2p/p2p/host/basic#BasicHost.Connect
)
. Alternatively,
we can manually
[
`AddAddr()`
](
https://godoc.org/github.com/libp2p/go-libp2p-peerstore#AddrManager.AddAddr
)
as in the example.
A
`basichost`
can now open streams (bi-directional channel between to peers)
using
[
NewStream
](
https://godoc.org/github.com/libp2p/go-libp2p/p2p/host/basic#BasicHost.NewStream
)
and use them to send and receive data tagged with a
`Protocol.ID`
(a
string). The host can also listen for incoming connections for a given
`Protocol`
with
[
`SetStreamHandle()`
](
https://godoc.org/github.com/libp2p/go-libp2p/p2p/host/basic#BasicHost.SetStreamHandler
)
.
The example makes use of all of this to enable communication between a
listener and a sender using protocol
`/echo/1.0.0`
(which could be any other thing).
This diff is collapsed.
Click to expand it.
examples/echo/main.go
View file @
ecc1c897
...
...
@@ -8,20 +8,22 @@ import (
"log"
"strings"
bhost
"github.com/libp2p/go-libp2p/p2p/host/basic"
golog
"github.com/ipfs/go-log"
host
"github.com/libp2p/go-libp2p-host"
inet
"github.com/libp2p/go-libp2p-net"
net
"github.com/libp2p/go-libp2p-net"
peer
"github.com/libp2p/go-libp2p-peer"
peerstore
"github.com/libp2p/go-libp2p-peerstore"
pstore
"github.com/libp2p/go-libp2p-peerstore"
swarm
"github.com/libp2p/go-libp2p-swarm"
bhost
"github.com/libp2p/go-libp2p/p2p/host/basic"
testutil
"github.com/libp2p/go-testutil"
ma
"github.com/multiformats/go-multiaddr"
gologging
"github.com/whyrusleeping/go-logging"
)
// create a 'Host' with a random peer to listen on the given address
func
make
Dummy
Host
(
listen
string
,
secio
bool
)
(
host
.
Host
,
error
)
{
func
make
Basic
Host
(
listen
string
,
secio
bool
)
(
host
.
Host
,
error
)
{
addr
,
err
:=
ma
.
NewMultiaddr
(
listen
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -61,30 +63,36 @@ func makeDummyHost(listen string, secio bool) (host.Host, error) {
}
func
main
()
{
golog
.
SetAllLoggers
(
gologging
.
INFO
)
// Change to DEBUG for extra info
listenF
:=
flag
.
Int
(
"l"
,
0
,
"wait for incoming connections"
)
target
:=
flag
.
String
(
"d"
,
""
,
"target peer to dial"
)
secio
:=
flag
.
Bool
(
"secio"
,
false
,
"enable secio"
)
flag
.
Parse
()
if
*
listenF
==
0
{
log
.
Fatal
(
"Please provide a port to bind on with -l"
)
}
listenaddr
:=
fmt
.
Sprintf
(
"/ip4/127.0.0.1/tcp/%d"
,
*
listenF
)
ha
,
err
:=
make
Dummy
Host
(
listenaddr
,
*
secio
)
ha
,
err
:=
make
Basic
Host
(
listenaddr
,
*
secio
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
// Set a stream handler on host A
ha
.
SetStreamHandler
(
"/echo/1.0.0"
,
func
(
s
net
.
Stream
)
{
log
.
Println
(
"got a new stream"
)
doEcho
(
s
)
log
.
Println
(
"Got a new stream!"
)
defer
s
.
Close
()
doEcho
(
s
)
})
if
*
target
==
""
{
log
.
Println
(
"listening for connections"
)
select
{}
// hang forever
}
// This is where the listener code ends
ipfsaddr
,
err
:=
ma
.
NewMultiaddr
(
*
target
)
if
err
!=
nil
{
...
...
@@ -102,25 +110,19 @@ func main() {
}
tptaddr
:=
strings
.
Split
(
ipfsaddr
.
String
(),
"/ipfs/"
)[
0
]
// This creates a MA with the "/ip4/ipaddr/tcp/port" part of the target
tptmaddr
,
err
:=
ma
.
NewMultiaddr
(
tptaddr
)
if
err
!=
nil
{
log
.
Fatalln
(
err
)
}
pi
:=
pstore
.
PeerInfo
{
ID
:
peerid
,
Addrs
:
[]
ma
.
Multiaddr
{
tptmaddr
},
}
log
.
Println
(
"connecting to target"
)
err
=
ha
.
Connect
(
context
.
Background
(),
pi
)
if
err
!=
nil
{
log
.
Fatalln
(
err
)
}
// We need to add the target to our peerstore, so we know how we can
// contact it
ha
.
Peerstore
()
.
AddAddr
(
peerid
,
tptmaddr
,
peerstore
.
PermanentAddrTTL
)
log
.
Println
(
"opening stream"
)
// make a new stream from host B to host A
// it should be handled on host A by the handler we set
// it should be handled on host A by the handler we set
above
s
,
err
:=
ha
.
NewStream
(
context
.
Background
(),
peerid
,
"/echo/1.0.0"
)
if
err
!=
nil
{
log
.
Fatalln
(
err
)
...
...
@@ -139,6 +141,8 @@ func main() {
log
.
Printf
(
"read reply: %q
\n
"
,
out
)
}
// doEcho reads some data from a stream, writes it back and closes the
// stream.
func
doEcho
(
s
inet
.
Stream
)
{
buf
:=
make
([]
byte
,
1024
)
n
,
err
:=
s
.
Read
(
buf
)
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Projects
Groups
Snippets
Help