138
distributed structural networking

Peer-to-Peer

Reference Wikipedia ↗
Peer-to-Peer — sequence diagram
Plate 138 sequence diagram

The Peer-to-Peer (P2P) pattern is a distributed application architecture that eliminates the need for a central server. Instead, individual nodes (peers) in the network share resources directly with each other. Each peer acts as both a client and a server, contributing its own resources (storage, bandwidth, processing power) to the network and consuming resources from other peers. This decentralization offers benefits like increased resilience, scalability, and reduced costs.

This pattern is particularly useful in scenarios where centralized control is undesirable or impractical, such as file sharing, content distribution, and collaborative systems. It’s also well-suited for applications that require high availability and can tolerate some level of inconsistency. P2P networks can be structured (with defined topologies) or unstructured (random connections), each offering different trade-offs in terms of efficiency and robustness.

Usage

  • File Sharing: Applications like BitTorrent rely heavily on P2P to distribute large files efficiently. Users download pieces of a file from multiple peers simultaneously, reducing the load on any single source.
  • Cryptocurrencies: Blockchain technologies, like those powering Bitcoin and Ethereum, are fundamentally P2P. Transactions are broadcast to the network and validated by multiple peers, ensuring security and transparency.
  • Decentralized Social Networks: Platforms like Mastodon utilize P2P principles through federated servers (instances) that communicate with each other, allowing users to interact across different communities without a single point of control.
  • Collaborative Editing: Some real-time collaborative editing tools use P2P to synchronize changes between users directly, reducing latency and improving responsiveness.

Examples

  • BitTorrent: A widely used protocol for P2P file sharing. Users download and upload file segments concurrently, creating a swarm of peers that collectively distribute the content. The tracker initially helps peers find each other, but the actual file transfer happens directly between peers.
  • IPFS (InterPlanetary File System): A P2P hypermedia protocol designed to make the web faster, safer, and more open. Content is addressed by its hash, and nodes store and serve content based on demand, creating a distributed content-addressable storage system.
  • WebRTC: A free and open-source project that provides real-time communication capabilities directly between browsers and mobile applications. It uses P2P connections for audio and video streaming, eliminating the need for a dedicated signaling server for media transfer (though signaling is still required for connection setup).

Specimens

15 implementations
Specimen 138.01 Dart View specimen ↗

The Peer-to-Peer pattern establishes direct communication and data exchange between participating entities (peers) without relying on a central server. Each peer acts as both a client and a server, sharing resources and responsibilities. In this Dart example, we simulate a basic peer-to-peer network using streams and stream controllers to represent peers exchanging messages. Each peer has a controller for sending to others and a stream to receive messages, effectively broadcasting messages to all connected peers. This can be extended with more sophisticated peer discovery and security. It’s idiomatic Dart due to its use of streams for asynchronous communication, mirroring how real-time event handling would be implemented.

// peers.dart
import 'dart:async';

class Peer {
  final String id;
  final StreamController<String> _controller = StreamController<String>.broadcast();

  Peer(this.id);

  Stream<String> get stream => _controller.stream;
  Sink<String> get sink => _controller.sink;

  void broadcast(String message) {
    sink.add("$id: $message");
  }
}

void main() {
  final peer1 = Peer('Peer1');
  final peer2 = Peer('Peer2');
  final peer3 = Peer('Peer3');

  peer1.broadcast('Hello, everyone!');
  peer2.broadcast('Hi Peer1!');
  peer3.broadcast('Greetings!');

  peer1.stream.listen((message) => print(message));
  peer2.stream.listen((message) => print(message));
  peer3.stream.listen((message) => print(message));
}