ceremonyclient/go-libp2p/examples/chat-with-mdns/README.md

109 lines
3.1 KiB
Markdown
Raw Normal View History

2023-08-21 03:50:38 +00:00
# p2p chat app with libp2p [support peer discovery using mdns]
This program demonstrates a simple p2p chat application. You will learn how to discover a peer in the network (using mdns), connect to it and open a chat stream. This example is heavily influenced by (and shamelessly copied from) `chat-with-rendezvous` example
## How to build this example?
```
go get -v -d ./...
go build
```
## Usage
Use two different terminal windows to run
```
./chat-with-mdns -port 6666
./chat-with-mdns -port 6668
```
## So how does it work?
1. **Configure a p2p host**
```go
ctx := context.Background()
// libp2p.New constructs a new libp2p Host.
// Other options can be added here.
host, err := libp2p.New()
```
[libp2p.New](https://godoc.org/github.com/libp2p/go-libp2p#New) is the constructor for libp2p node. It creates a host with given configuration.
2. **Set a default handler function for incoming connections.**
This function is called on the local peer when a remote peer initiate a connection and starts a stream with the local peer.
```go
// Set a function as stream handler.
host.SetStreamHandler("/chat/1.1.0", handleStream)
```
```handleStream``` is executed for each new stream incoming to the local peer. ```stream``` is used to exchange data between local and remote peer. This example uses non blocking functions for reading and writing from this stream.
```go
func handleStream(stream net.Stream) {
// Create a buffer stream for non blocking read and write.
rw := bufio.NewReadWriter(bufio.NewReader(stream), bufio.NewWriter(stream))
go readData(rw)
go writeData(rw)
// 'stream' will stay open until you close it (or the other side closes it).
}
```
3. **Find peers nearby using mdns**
2024-06-08 11:32:45 +00:00
New [mdns discovery](https://godoc.org/github.com/libp2p/go-libp2p/p2p/discovery#NewMdnsService) service in host.
2023-08-21 03:50:38 +00:00
```go
2024-06-08 11:32:45 +00:00
notifee := &discoveryNotifee{PeerChan: make(chan peer.AddrInfo)}
ser, err := discovery.NewMdnsService(peerhost, rendezvous, notifee)
2023-08-21 03:50:38 +00:00
```
register [Notifee interface](https://godoc.org/github.com/libp2p/go-libp2p/p2p/discovery#Notifee) with service so that we get notified about peer discovery
```go
2024-06-08 11:32:45 +00:00
ser.Start()
2023-08-21 03:50:38 +00:00
```
2024-06-08 11:32:45 +00:00
2023-08-21 03:50:38 +00:00
4. **Open streams to peers found.**
Finally we open stream to the peers we found, as we find them
```go
peer := <-peerChan // will block until we discover a peer
2024-06-08 11:32:45 +00:00
// this is used to avoid call `NewStream` from both side
if peer.ID > host.ID() {
// if other end peer id greater than us, don't connect to it, just wait for it to connect us
fmt.Println("Found peer:", peer, " id is greater than us, wait for it to connect to us")
continue
}
2023-08-21 03:50:38 +00:00
fmt.Println("Found peer:", peer, ", connecting")
if err := host.Connect(ctx, peer); err != nil {
fmt.Println("Connection failed:", err)
2024-06-08 11:32:45 +00:00
continue
2023-08-21 03:50:38 +00:00
}
// open a stream, this stream will be handled by handleStream other end
stream, err := host.NewStream(ctx, peer.ID, protocol.ID(cfg.ProtocolID))
if err != nil {
fmt.Println("Stream open failed", err)
} else {
rw := bufio.NewReadWriter(bufio.NewReader(stream), bufio.NewWriter(stream))
go writeData(rw)
go readData(rw)
fmt.Println("Connected to:", peer)
}
```
## Authors
1. Bineesh Lazar