aboutsummaryrefslogtreecommitdiffstats
path: root/examples/network.rs
diff options
context:
space:
mode:
Diffstat (limited to 'examples/network.rs')
-rw-r--r--examples/network.rs86
1 files changed, 86 insertions, 0 deletions
diff --git a/examples/network.rs b/examples/network.rs
new file mode 100644
index 0000000..be3e0ef
--- /dev/null
+++ b/examples/network.rs
@@ -0,0 +1,86 @@
+//! Multi-node network example (equivalent to example2.cpp).
+//!
+//! Creates N nodes on localhost, joins them recursively
+//! via the first node, then prints state periodically.
+//!
+//! Usage:
+//! cargo run --example network
+//! RUST_LOG=debug cargo run --example network
+
+use std::time::{Duration, Instant};
+use tesseras_dht::Node;
+use tesseras_dht::nat::NatState;
+
+const NUM_NODES: usize = 20;
+const POLL_ROUNDS: usize = 30;
+
+fn main() {
+ env_logger::Builder::from_env(
+ env_logger::Env::default().default_filter_or("info"),
+ )
+ .format(|buf, record| {
+ use std::io::Write;
+ writeln!(
+ buf,
+ "{} [{}] {}",
+ record.level(),
+ record.target(),
+ record.args()
+ )
+ })
+ .init();
+
+ println!("Creating {NUM_NODES} nodes...");
+ let start = Instant::now();
+
+ // Create bootstrap node
+ let mut nodes: Vec<Node> = Vec::new();
+ let bootstrap = Node::bind(0).expect("bind bootstrap");
+ let bootstrap_port = bootstrap.local_addr().unwrap().port();
+ println!("Bootstrap: {} @ port {bootstrap_port}", bootstrap.id_hex());
+ nodes.push(bootstrap);
+
+ // Create and join remaining nodes
+ for i in 1..NUM_NODES {
+ let mut node = Node::bind(0).expect("bind node");
+ node.set_nat_state(NatState::Global);
+ node.join("127.0.0.1", bootstrap_port).expect("join");
+ println!("Node {i}: {} joined", &node.id_hex()[..8]);
+ nodes.push(node);
+ }
+ nodes[0].set_nat_state(NatState::Global);
+
+ println!("\nAll {NUM_NODES} nodes created in {:?}", start.elapsed());
+
+ // Poll all nodes to exchange messages
+ println!("\nPolling {POLL_ROUNDS} rounds...");
+ for round in 0..POLL_ROUNDS {
+ for node in nodes.iter_mut() {
+ node.poll().ok();
+ }
+ std::thread::sleep(Duration::from_millis(50));
+
+ if (round + 1) % 10 == 0 {
+ let sizes: Vec<usize> =
+ nodes.iter().map(|n| n.routing_table_size()).collect();
+ let avg = sizes.iter().sum::<usize>() / sizes.len();
+ let max = sizes.iter().max().unwrap();
+ println!(
+ " Round {}: avg routing table = {avg}, max = {max}",
+ round + 1
+ );
+ }
+ }
+
+ // Print final state
+ println!("\n--- Final state ---");
+ for (i, node) in nodes.iter().enumerate() {
+ println!(
+ "Node {i}: {} | rt={} peers={} storage={}",
+ &node.id_hex()[..8],
+ node.routing_table_size(),
+ node.peer_count(),
+ node.storage_count(),
+ );
+ }
+}