CrackedRuby CrackedRuby

Overview

Network topology describes the arrangement of various elements (links, nodes, devices) in a computer network. The topology determines how devices communicate, how data travels through the network, and how the network behaves under different conditions. Understanding network topologies provides the foundation for designing distributed systems, microservices architectures, and any application requiring inter-process communication.

Two primary classifications exist: physical topology describes the actual physical layout of cables and devices, while logical topology describes how data flows through the network regardless of physical layout. A network may have different physical and logical topologies simultaneously. For example, Ethernet networks physically arranged in a star configuration often operate as a logical bus topology.

Network topology affects several critical system properties: fault tolerance (how the network handles device or connection failures), scalability (how easily the network accommodates new nodes), performance (throughput and latency characteristics), cost (hardware and maintenance expenses), and complexity (difficulty of installation and troubleshooting).

# Representing a simple network node
class NetworkNode
  attr_reader :id, :connections
  
  def initialize(id)
    @id = id
    @connections = []
  end
  
  def connect_to(node)
    @connections << node unless @connections.include?(node)
    node.connections << self unless node.connections.include?(self)
  end
  
  def send_message(message, target_id, visited = Set.new)
    return message if @id == target_id
    return nil if visited.include?(@id)
    
    visited.add(@id)
    @connections.each do |neighbor|
      result = neighbor.send_message(message, target_id, visited)
      return result if result
    end
    nil
  end
end

Key Principles

Network topologies follow fundamental organizational patterns that determine connectivity and communication characteristics. Each topology represents a distinct graph structure where nodes represent devices and edges represent communication links.

Bus Topology arranges all nodes along a single communication line. Each device connects to a central cable (the bus), and data transmitted by any device travels along the entire bus until reaching its destination. All devices receive all transmissions, but only the intended recipient processes the data. This topology requires terminators at both ends of the bus to prevent signal reflection.

Star Topology connects all nodes to a central hub or switch. Each device has a dedicated point-to-point connection to the central device, which manages all communication. Data passes through the hub, which can either broadcast to all devices or intelligently route to specific destinations. The central device acts as a repeater, regenerating signals and managing traffic flow.

Ring Topology connects each node to exactly two other nodes, forming a closed loop. Data travels in one direction (unidirectional ring) or both directions (bidirectional ring) around the circle. Each device acts as a repeater, receiving data and passing it to the next device until reaching the destination. Token-passing protocols often coordinate access in ring networks.

Mesh Topology provides multiple paths between nodes through direct connections. Full mesh topology connects every node to every other node directly, creating n(n-1)/2 connections for n nodes. Partial mesh topology connects some nodes to multiple neighbors while others have fewer connections. Mesh networks excel at fault tolerance since communication can route around failures.

Tree Topology (hierarchical topology) arranges nodes in a hierarchy with a root node at the top and branches extending downward. Each non-root node connects to exactly one parent node and zero or more child nodes. This structure reflects organizational hierarchies and enables efficient routing in many scenarios.

Hybrid Topology combines two or more basic topologies to create complex network structures tailored to specific requirements. Star-bus hybrids connect multiple star networks via a bus backbone. Star-ring hybrids connect star networks in a ring configuration. These combinations balance the advantages and disadvantages of individual topologies.

Network topology fundamentally affects routing complexity, measured by the number of hops required between nodes. A hop represents one transmission between adjacent devices. Minimizing hops reduces latency but may increase hardware costs or complexity.

Broadcast domains define groups of devices that receive broadcast messages. Topology determines broadcast domain size and isolation. Collision domains identify sets of devices competing for the same communication medium. Modern switched networks create separate collision domains for each port, while older shared-medium networks had single collision domains.

Design Considerations

Selecting a network topology requires analyzing multiple factors including scale, reliability requirements, budget constraints, and growth projections. Each topology presents distinct trade-offs affecting the overall system architecture.

Fault Tolerance Analysis examines network behavior during component failures. Star topology creates a single point of failure at the central hub - hub failure disconnects all nodes, but individual device failures affect only that device. Mesh topology provides maximum fault tolerance through redundant paths, automatically routing around failures. Ring topology fails completely if any device or connection breaks in a unidirectional ring, though bidirectional rings maintain connectivity. Bus topology fails entirely if the main cable breaks, though individual device failures only affect that device.

Scalability Requirements determine how easily the network accommodates growth. Star topology scales relatively well - adding nodes requires only a new cable to the hub and an available port. However, hub port limitations eventually constrain growth. Mesh topology scales poorly beyond small networks due to exponential connection growth (full mesh requires n-squared connections). Bus topology experiences performance degradation as more devices share the same medium, increasing collision probability. Tree topology scales hierarchically, adding branches at appropriate levels without affecting other sections.

Performance Characteristics vary significantly across topologies. Star topology centralizes traffic management, potentially creating bottlenecks at the hub but enabling intelligent switching. Mesh topology distributes load across multiple paths, balancing traffic and avoiding congestion. Ring topology provides predictable latency through deterministic token-passing but limits throughput to the ring's bandwidth. Bus topology suffers from collision-related performance degradation as node count increases.

Cost Analysis includes hardware, installation, and maintenance expenses. Bus topology minimizes cable requirements but needs quality termination. Star topology requires more cable (home-run from each device to hub) but simplifies troubleshooting. Mesh topology demands the most cabling and network interfaces but provides redundancy without additional hardware. Organizations must balance initial deployment costs against long-term operational expenses.

Management Complexity affects troubleshooting difficulty and operational overhead. Star topology centralizes management and simplifies fault isolation - problems typically occur at the hub or in specific device connections. Mesh topology complicates troubleshooting since multiple paths exist between devices. Ring topology requires careful monitoring since each device affects network operation. Bus topology presents difficult troubleshooting when problems occur in the shared medium.

# Evaluating topology characteristics
class TopologyEvaluator
  def self.calculate_metrics(topology_type, node_count)
    case topology_type
    when :star
      {
        connections: node_count,
        max_hops: 2,
        single_point_failure: true,
        complexity: :low
      }
    when :full_mesh
      {
        connections: node_count * (node_count - 1) / 2,
        max_hops: 1,
        single_point_failure: false,
        complexity: :high
      }
    when :ring
      {
        connections: node_count,
        max_hops: node_count / 2,
        single_point_failure: true,
        complexity: :medium
      }
    when :bus
      {
        connections: node_count,
        max_hops: 1,
        single_point_failure: true,
        complexity: :medium
      }
    end
  end
end

# Compare topologies for a 10-node network
[:star, :full_mesh, :ring, :bus].each do |topology|
  metrics = TopologyEvaluator.calculate_metrics(topology, 10)
  puts "#{topology.upcase}: #{metrics[:connections]} connections, max #{metrics[:max_hops]} hops"
end
# => STAR: 10 connections, max 2 hops
# => FULL_MESH: 45 connections, max 1 hops
# => RING: 10 connections, max 5 hops
# => BUS: 10 connections, max 1 hops

Ruby Implementation

Ruby provides several approaches for implementing network topology concepts through socket programming, networking libraries, and distributed system frameworks. The standard library includes TCPServer and TCPSocket for connection-oriented communication, and UDPSocket for connectionless communication.

Implementing Star Topology using Ruby requires a central server managing client connections. The server accepts multiple client connections and routes messages between them:

require 'socket'
require 'json'

class StarTopologyHub
  def initialize(port)
    @server = TCPServer.new(port)
    @clients = {}
    @mutex = Mutex.new
  end
  
  def start
    puts "Hub listening on port #{@server.addr[1]}"
    
    loop do
      Thread.start(@server.accept) do |client|
        handle_client(client)
      end
    end
  end
  
  private
  
  def handle_client(client)
    client_id = register_client(client)
    puts "Client #{client_id} connected"
    
    loop do
      message = client.gets
      break unless message
      
      data = JSON.parse(message)
      route_message(client_id, data)
    end
  rescue => e
    puts "Error handling client: #{e.message}"
  ensure
    unregister_client(client_id) if client_id
    client.close
  end
  
  def register_client(client)
    @mutex.synchronize do
      id = @clients.size + 1
      @clients[id] = client
      id
    end
  end
  
  def unregister_client(client_id)
    @mutex.synchronize do
      @clients.delete(client_id)
    end
  end
  
  def route_message(from_id, data)
    target_id = data['target']
    
    @mutex.synchronize do
      if target_id == 'broadcast'
        @clients.each do |id, client|
          client.puts(data.to_json) unless id == from_id
        end
      elsif @clients[target_id]
        @clients[target_id].puts(data.to_json)
      end
    end
  end
end

Implementing Mesh Topology requires peer-to-peer connections where each node maintains connections to multiple other nodes:

class MeshNode
  attr_reader :id, :port
  
  def initialize(id, port)
    @id = id
    @port = port
    @peers = {}
    @server = TCPServer.new(port)
    @mutex = Mutex.new
    @running = true
  end
  
  def start
    Thread.new { accept_connections }
    self
  end
  
  def connect_to_peer(peer_host, peer_port, peer_id)
    socket = TCPSocket.new(peer_host, peer_port)
    register_peer(peer_id, socket)
    
    # Send identification
    socket.puts(JSON.generate({type: 'identify', id: @id}))
    
    # Start receiving thread
    Thread.new { receive_from_peer(peer_id, socket) }
  end
  
  def broadcast(message)
    data = {type: 'message', from: @id, content: message}
    
    @mutex.synchronize do
      @peers.each_value do |socket|
        socket.puts(JSON.generate(data))
      end
    end
  end
  
  def send_to(peer_id, message)
    @mutex.synchronize do
      if socket = @peers[peer_id]
        data = {type: 'message', from: @id, content: message}
        socket.puts(JSON.generate(data))
      end
    end
  end
  
  def stop
    @running = false
    @server.close
    @mutex.synchronize do
      @peers.each_value(&:close)
    end
  end
  
  private
  
  def accept_connections
    while @running
      socket = @server.accept
      Thread.new { handle_incoming_connection(socket) }
    end
  rescue IOError
    # Server closed
  end
  
  def handle_incoming_connection(socket)
    # Wait for identification
    data = JSON.parse(socket.gets)
    peer_id = data['id']
    
    register_peer(peer_id, socket)
    receive_from_peer(peer_id, socket)
  rescue => e
    puts "Error handling incoming connection: #{e.message}"
    socket.close
  end
  
  def receive_from_peer(peer_id, socket)
    loop do
      line = socket.gets
      break unless line
      
      data = JSON.parse(line)
      handle_message(peer_id, data)
    end
  rescue => e
    puts "Error receiving from peer #{peer_id}: #{e.message}"
  ensure
    unregister_peer(peer_id)
  end
  
  def register_peer(peer_id, socket)
    @mutex.synchronize do
      @peers[peer_id] = socket
    end
  end
  
  def unregister_peer(peer_id)
    @mutex.synchronize do
      @peers.delete(peer_id)
    end
  end
  
  def handle_message(from_id, data)
    puts "Node #{@id} received from #{from_id}: #{data['content']}"
  end
end

Ring Topology Implementation passes messages sequentially around a circle:

class RingNode
  attr_reader :id
  attr_accessor :next_node
  
  def initialize(id)
    @id = id
    @next_node = nil
    @message_queue = Queue.new
    @processed_messages = Set.new
  end
  
  def start
    Thread.new { process_messages }
  end
  
  def send_message(target_id, content)
    message = {
      id: SecureRandom.uuid,
      target: target_id,
      content: content,
      hops: 0
    }
    @message_queue << message
  end
  
  def receive_message(message)
    @message_queue << message
  end
  
  private
  
  def process_messages
    loop do
      message = @message_queue.pop
      
      # Avoid processing same message twice
      next if @processed_messages.include?(message[:id])
      @processed_messages.add(message[:id])
      
      if message[:target] == @id
        puts "Node #{@id} received: #{message[:content]}"
      else
        # Forward to next node
        message[:hops] += 1
        if @next_node && message[:hops] < 100  # Prevent infinite loops
          @next_node.receive_message(message)
        end
      end
    end
  end
end

# Create and connect ring
nodes = (1..5).map { |i| RingNode.new(i) }
nodes.each_with_index do |node, i|
  node.next_node = nodes[(i + 1) % nodes.size]
  node.start
end

# Send message around ring
nodes[0].send_message(3, "Hello from node 1!")
# => Node 3 received: Hello from node 1!

Using Ruby Networking Gems extends built-in functionality. EventMachine provides event-driven networking, while Celluloid::IO offers concurrent socket operations:

require 'eventmachine'

class EventMachineStar < EventMachine::Connection
  @@clients = {}
  
  def post_init
    @client_id = @@clients.size + 1
    @@clients[@client_id] = self
    puts "Client #{@client_id} connected"
  end
  
  def receive_data(data)
    msg = JSON.parse(data)
    
    case msg['type']
    when 'broadcast'
      @@clients.each do |id, client|
        client.send_data(data) unless id == @client_id
      end
    when 'direct'
      target = @@clients[msg['target']]
      target.send_data(data) if target
    end
  rescue => e
    puts "Error: #{e.message}"
  end
  
  def unbind
    @@clients.delete(@client_id)
    puts "Client #{@client_id} disconnected"
  end
end

# EventMachine.run do
#   EventMachine.start_server('0.0.0.0', 8080, EventMachineStar)
# end

Implementation Approaches

Implementing network topologies in software systems requires selecting appropriate communication patterns and infrastructure. The approach depends on whether building physical networks, distributed systems, or application-level communication.

Socket-Based Implementation uses operating system socket APIs for direct node-to-node communication. This low-level approach provides fine-grained control over connections and data flow. Star topology implementation creates a central server accepting multiple client connections. Ring topology establishes connections between adjacent nodes in the sequence. Mesh topology requires each node to maintain sockets to all or many other nodes. This approach suits applications requiring custom protocols or minimal dependencies.

Message Queue Implementation decouples nodes through intermediary message brokers. Producers send messages to queues or topics, consumers receive messages from subscriptions. This approach naturally implements publish-subscribe patterns similar to bus topology. RabbitMQ, Redis, and Apache Kafka provide message queue infrastructure. Applications define logical topologies through queue and exchange configuration rather than direct node connections. This approach handles scaling and fault tolerance at the infrastructure level.

Service Mesh Architecture manages service-to-service communication in microservices deployments. A sidecar proxy accompanies each service instance, handling networking concerns including routing, load balancing, and observability. The control plane configures proxy behavior, creating logical topologies independent of physical deployment. Istio and Linkerd exemplify service mesh implementations. This approach separates application code from network topology management.

Overlay Networks create virtual topologies atop physical networks. Software-defined networking (SDN) separates the control plane from the data plane, allowing dynamic topology reconfiguration. Container orchestration platforms like Kubernetes create overlay networks connecting containers across multiple hosts. Virtual private networks (VPNs) establish mesh or star topologies over the public internet. This approach provides flexibility to change logical topology without physical infrastructure changes.

Hybrid Approaches combine multiple strategies for different system layers. A service mesh might manage microservice communication while message queues handle asynchronous workflows. Applications use direct socket connections for low-latency operations and message queues for reliable delivery. The physical network infrastructure might use star topology while the application implements logical mesh routing.

# Abstract topology interface for different implementations
class TopologyStrategy
  def connect(node)
    raise NotImplementedError
  end
  
  def send_message(target, message)
    raise NotImplementedError
  end
  
  def broadcast(message)
    raise NotImplementedError
  end
end

class StarTopologyStrategy < TopologyStrategy
  def initialize(hub_host, hub_port)
    @hub = TCPSocket.new(hub_host, hub_port)
  end
  
  def send_message(target, message)
    data = {type: 'direct', target: target, message: message}
    @hub.puts(JSON.generate(data))
  end
  
  def broadcast(message)
    data = {type: 'broadcast', message: message}
    @hub.puts(JSON.generate(data))
  end
end

class MeshTopologyStrategy < TopologyStrategy
  def initialize
    @connections = {}
  end
  
  def connect(node_id, host, port)
    @connections[node_id] = TCPSocket.new(host, port)
  end
  
  def send_message(target, message)
    if socket = @connections[target]
      socket.puts(JSON.generate({message: message}))
    end
  end
  
  def broadcast(message)
    @connections.each_value do |socket|
      socket.puts(JSON.generate({message: message}))
    end
  end
end

# Application uses strategy pattern for topology independence
class DistributedApplication
  def initialize(topology_strategy)
    @topology = topology_strategy
  end
  
  def notify_peer(peer_id, event)
    @topology.send_message(peer_id, event)
  end
  
  def notify_all(event)
    @topology.broadcast(event)
  end
end

Performance Considerations

Network topology significantly impacts application performance through latency, throughput, and scalability characteristics. Understanding these implications guides topology selection and optimization strategies.

Latency Analysis examines message delay from source to destination. Star topology requires two hops maximum - source to hub, hub to destination - providing predictable low latency. Mesh topology achieves minimum latency with direct peer-to-peer connections requiring only one hop. Ring topology exhibits variable latency depending on source and destination positions, with maximum delay equal to half the ring circumference. Tree topology latency depends on the distance between nodes in the hierarchy, potentially requiring multiple hops up to a common ancestor and down to the destination.

Throughput Characteristics determine aggregate network capacity. Star topology centralizes traffic at the hub, making hub bandwidth the limiting factor. Modern switched hubs provide dedicated bandwidth per port, aggregating capacity effectively. Mesh topology distributes load across multiple paths, maximizing aggregate throughput since each link carries only traffic between its endpoints. Ring topology limits throughput to the ring's bandwidth since all traffic shares the medium. Bus topology suffers from collision overhead, reducing effective throughput as utilization increases.

Concurrent Connection Overhead affects system resources as node count grows. Each network connection consumes memory for buffers, file descriptors, and connection state. Star topology minimizes per-node connection count - each node maintains one connection to the hub. Full mesh topology requires each node to maintain connections to all other nodes, creating O(n²) total connections that strain system resources. Partial mesh reduces connection count while maintaining redundancy benefits.

require 'benchmark'

# Comparing message routing performance
class PerformanceComparison
  def self.benchmark_star(node_count, message_count)
    hub = StarHub.new
    nodes = node_count.times.map { |i| StarClient.new(i, hub) }
    
    Benchmark.measure do
      message_count.times do |i|
        source = nodes[rand(node_count)]
        target = rand(node_count)
        source.send_message(target, "Message #{i}")
      end
    end
  end
  
  def self.benchmark_mesh(node_count, message_count)
    nodes = node_count.times.map { |i| MeshPeer.new(i) }
    
    # Establish full mesh connections
    nodes.combination(2).each do |n1, n2|
      n1.connect_to(n2)
    end
    
    Benchmark.measure do
      message_count.times do |i|
        source = nodes[rand(node_count)]
        target = rand(node_count)
        source.send_direct(target, "Message #{i}")
      end
    end
  end
end

# Star hub implementation
class StarHub
  def initialize
    @clients = {}
  end
  
  def register(client)
    @clients[client.id] = client
  end
  
  def route(from_id, to_id, message)
    @clients[to_id]&.receive(message)
  end
end

class StarClient
  attr_reader :id
  
  def initialize(id, hub)
    @id = id
    @hub = hub
    @hub.register(self)
  end
  
  def send_message(target_id, message)
    @hub.route(@id, target_id, message)
  end
  
  def receive(message)
    # Process message
  end
end

# Mesh peer implementation
class MeshPeer
  attr_reader :id
  
  def initialize(id)
    @id = id
    @connections = {}
  end
  
  def connect_to(peer)
    @connections[peer.id] = peer
    peer.connections[id] = self
  end
  
  def send_direct(target_id, message)
    @connections[target_id]&.receive(message)
  end
  
  def receive(message)
    # Process message
  end
  
  protected
  
  attr_reader :connections
end

Memory Utilization varies by topology. Star topology memory usage scales linearly with node count at the hub and remains constant at client nodes. Mesh topology requires each node to store connection information for all peers, creating O(n) memory usage per node. Ring topology maintains minimal connection state - each node tracks only its immediate neighbors.

Network Congestion occurs when traffic exceeds available bandwidth. Star topology concentrates congestion at the hub, simplifying monitoring but creating a potential bottleneck. Mesh topology distributes congestion across multiple links, complicating diagnosis but preventing single points of failure. Implementing backpressure mechanisms prevents congestion from cascading through the network.

Scaling Patterns determine how performance changes with growth. Star topology scales vertically at the hub - adding more powerful hardware improves overall capacity. Horizontal scaling requires additional hubs and careful traffic distribution. Mesh topology scales horizontally since each node contributes resources, but connection overhead limits practical size. Hierarchical topologies (tree, hybrid) scale well by partitioning the network into manageable segments.

Real-World Applications

Network topologies appear throughout production systems, from physical infrastructure to application architecture patterns. Understanding real-world implementations provides context for topology selection and configuration.

Data Center Networks commonly implement hierarchical topologies combining multiple patterns. The core layer uses mesh or partial mesh topology connecting high-capacity switches. The distribution layer implements star topology with access switches connecting to distribution switches. The access layer uses star topology connecting servers to access switches. This three-tier hierarchy balances cost, performance, and fault tolerance. Modern data centers increasingly adopt leaf-spine architectures - a two-tier mesh connecting leaf switches (access layer) to spine switches (core layer) providing consistent latency and high bandwidth.

Microservices Communication leverages multiple topology patterns simultaneously. Service discovery creates a logical star topology where a central registry tracks service locations. Direct service-to-service communication creates a mesh topology with each service potentially connecting to multiple others. Message brokers introduce bus topology for asynchronous workflows and event distribution. Circuit breakers and retry policies handle partial failures inherent in distributed topologies.

# Service mesh topology in microservices
class ServiceRegistry
  def initialize
    @services = {}
    @mutex = Mutex.new
  end
  
  def register(service_name, instance_id, host, port)
    @mutex.synchronize do
      @services[service_name] ||= []
      @services[service_name] << {
        id: instance_id,
        host: host,
        port: port,
        registered_at: Time.now
      }
    end
  end
  
  def discover(service_name)
    @mutex.synchronize do
      @services[service_name]&.sample  # Simple load balancing
    end
  end
  
  def unregister(service_name, instance_id)
    @mutex.synchronize do
      @services[service_name]&.reject! { |s| s[:id] == instance_id }
    end
  end
end

class Microservice
  def initialize(name, registry)
    @name = name
    @id = SecureRandom.uuid
    @registry = registry
    @registry.register(@name, @id, 'localhost', 8080)
  end
  
  def call_service(service_name, method, params)
    instance = @registry.discover(service_name)
    return nil unless instance
    
    # Make HTTP request to discovered instance
    uri = URI("http://#{instance[:host]}:#{instance[:port]}/#{method}")
    # ... actual HTTP request implementation
  end
  
  def shutdown
    @registry.unregister(@name, @id)
  end
end

Content Delivery Networks (CDNs) implement distributed mesh-like topologies. Origin servers connect to edge servers distributed globally. Edge servers cache content and serve requests from nearby clients. This topology reduces latency by positioning content closer to users. Anycast routing directs traffic to the nearest edge server. Cache invalidation propagates through the network when content updates.

Blockchain Networks implement peer-to-peer mesh topologies where each node connects to multiple peers. Transactions and blocks propagate through the network via gossip protocols. No central authority controls communication - each node independently validates and forwards data. Network partition tolerance and eventual consistency emerge from this decentralized structure.

IoT Deployments frequently combine topologies based on device capabilities and requirements. Resource-constrained sensors communicate via star topology to gateway devices. Gateways form mesh networks for redundancy and coverage extension. Cloud platforms aggregate data from multiple gateways. This hierarchical approach balances power consumption, bandwidth, and reliability.

WebSocket Architectures often implement hub-and-spoke patterns (star topology) for real-time communication. A central WebSocket server maintains persistent connections to multiple clients. Clients send messages to the server, which broadcasts or routes to appropriate recipients. This pattern suits chat applications, collaborative editing, and live dashboards.

require 'faye/websocket'

class WebSocketHub
  def initialize
    @clients = {}
    @rooms = Hash.new { |h, k| h[k] = Set.new }
  end
  
  def handle_connection(env)
    ws = Faye::WebSocket.new(env)
    client_id = SecureRandom.uuid
    
    ws.on :open do |event|
      @clients[client_id] = ws
      send_to_client(client_id, {type: 'connected', id: client_id})
    end
    
    ws.on :message do |event|
      handle_message(client_id, JSON.parse(event.data))
    end
    
    ws.on :close do |event|
      @clients.delete(client_id)
      @rooms.each_value { |members| members.delete(client_id) }
    end
    
    ws.rack_response
  end
  
  private
  
  def handle_message(client_id, data)
    case data['type']
    when 'join'
      @rooms[data['room']].add(client_id)
    when 'leave'
      @rooms[data['room']].delete(client_id)
    when 'room_message'
      broadcast_to_room(data['room'], client_id, data['content'])
    when 'direct'
      send_to_client(data['target'], data)
    end
  end
  
  def broadcast_to_room(room, sender_id, content)
    message = {type: 'room_message', content: content, from: sender_id}
    @rooms[room].each do |client_id|
      send_to_client(client_id, message) unless client_id == sender_id
    end
  end
  
  def send_to_client(client_id, data)
    @clients[client_id]&.send(JSON.generate(data))
  end
end

Container Orchestration creates overlay networks implementing various topologies. Kubernetes establishes a flat network where all pods communicate directly (mesh-like topology) while services implement load balancing (star topology from client perspective). Network policies enforce segmentation creating logical topologies independent of physical layout.

Reference

Topology Comparison Matrix

Topology Connections Max Hops Fault Tolerance Scalability Cost
Star n 2 Low (hub SPOF) Medium Medium
Ring n n/2 Low Poor Low
Bus n 1 Low Poor Low
Tree n-1 2*log(n) Medium Good Medium
Full Mesh n(n-1)/2 1 High Poor High
Partial Mesh Varies Varies Medium-High Medium Medium-High

Topology Characteristics

Characteristic Best Topology Worst Topology Trade-off Considerations
Latency Mesh Ring Direct connections vs routing complexity
Fault Tolerance Mesh Ring/Bus Redundancy vs cost and complexity
Installation Cost Bus Full Mesh Cable requirements vs reliability
Maintenance Star Mesh Centralized vs distributed management
Bandwidth Efficiency Mesh Bus Dedicated vs shared medium
Broadcast Performance Bus Mesh Shared medium vs multiple transmissions

Ruby Socket Operations

Operation TCP Example UDP Example Use Case
Server Creation TCPServer.new(port) UDPSocket.new Accept connections or bind port
Client Connection TCPSocket.new(host, port) socket.connect(host, port) Establish communication
Send Data socket.write(data) socket.send(data, 0, host, port) Transmit messages
Receive Data socket.read / socket.gets socket.recvfrom(maxlen) Read incoming data
Close Connection socket.close socket.close Clean up resources
Set Timeout socket.setsockopt socket.setsockopt Prevent blocking indefinitely

Topology Selection Criteria

Scenario Recommended Topology Reasoning
Small office network Star Centralized management, simple troubleshooting
IoT sensor network Tree Hierarchical data aggregation, scalable
High availability cluster Mesh Redundant paths, no single point of failure
Legacy industrial control Ring Deterministic timing, token-passing protocols
Temporary deployment Bus Minimal infrastructure, easy setup
Microservices architecture Hybrid (mesh + star) Flexibility, service discovery, direct communication
Real-time collaboration Star Centralized coordination, efficient broadcasting
Blockchain network Mesh Decentralized, peer-to-peer consensus

Network Topology Metrics

Metric Definition Calculation Significance
Node Degree Connections per node count(connections) Resource requirements per node
Network Diameter Maximum shortest path max(shortest_path(i,j)) Worst-case latency
Average Path Length Mean path length avg(shortest_path(i,j)) Typical communication delay
Clustering Coefficient Local interconnection density connected_neighbors / possible_neighbors Network cohesion measure
Bisection Bandwidth Minimum cut capacity min(cut_bandwidth) Network bottleneck identification

Ruby Networking Libraries

Library Purpose Topology Support Key Features
Socket (stdlib) Low-level networking All TCP, UDP, Unix sockets
EventMachine Event-driven I/O Star, Mesh Non-blocking, high concurrency
Celluloid Actor-based concurrency All Concurrent objects, supervision
ActionCable WebSocket framework Star (hub-spoke) Rails integration, channels
Bunny RabbitMQ client Bus (pub-sub) Message queuing, routing
Redis-rb Redis client Bus (pub-sub) Key-value, streams, pub-sub