Introduction
Traditional communication is client-server based. The client initiates a connection to the server, and communicates with the server using a protocol suited for that server. As an example: suppose we have two WhatsApp clients lets say A
and B. And A wants to send a message to B. Typically, they both initiate a connection to the server. A sends a message to the server and tells the server to relay this message to B. The server knows both clients so this
communication is pretty straightforward.
In a peer-to-peer network (P2P), this communication happens quite differently. There is no longer a server, only clients (commonly they are referred to as nodes or peers) organized in a mesh network, and they communicate directly
to each other. For this to work a few challenges have to be solved:
-
How do the nodes know and find each other? In a client-server communication, the client established the connection to the server, and the server is known by some pre-defined ip address (or addresses). In a P2P mesh network how to know the ip address of the client? Potentially, the client is roaming which means its ip address can change over time. In libp2p this is solved by mDNS, DHT/Kademlia, and more.
-
How can a node directly connect to another node? In client-server communication, the client initiates a connection to the server. This is an outbound connection. However, in a P2P connection, a node connects directly to another node, which is an inbound connection. Inbound connections are not always possible. Think of security/firewall (the router rejects inbound connection attempts), but also think of NAT devices (what is the correct ip address? A node might know a different ip address of itself than the outside world is able to connect to) In libp2p this is solved by autonat, holepunching, relay-service, and more.
-
Which wire protocol to use? In a client-server network the used protocol is obvious: the server dictates the protocol to be used, or else it rejects the connection. A server can easily support the current protocol version while also supporting the older version(s) temporarily. A server can also force a client upgrade. In a P2P network this is not obvious, because there are several nodes connected to each other. They all could have a different implementation with different capabilities and with different versions In libp2p this is solved by multiformats.
-
How to distribute content? In a client/server setup, this is almost trivial. If node
Awants to send something to nodeBit ’tags’ the message with an ‘address’ or ‘phone-number’ and sends it to the server. Since the server knowsBit forwards this message directly toB. In a P2P connection, however, all nodes are interconnected via a mesh and perhapsAdoes not have a direct connection toBbut has an indirect connection via some intermediate nodesC,DandE. IfAwants to send something toBit has to send it toC.Chas to send it toDand so on until it reachesB. It has to find a ‘route’ through all the nodes fromAtoB. And, for efficiency reasons,Cshould not forward the message to all its peers, because this will lead to congestion; all messages are send to each and every node. Ideally,Cshould send the message only to a node that is the most optimal node in the route toB(This is not always achievable). In libp2p this is solved using different pubsub mechanisms.
There already exists some P2P network protocols, but they lacked standardization. Libp2p standardizes they way nodes communicate to each other and has a solution for the above-mentioned issues (and more).
For an in-depth description of libp2p, please see: https://libp2p.io/