CodeBlanks Logo Icon CodeBlanks

Broadcast

Write to all clients through a Vec<TcpStream>.

Broadcast

When a message arrives, it must be forwarded to everyone except the sender. Separating the broadcast logic from the network makes testing easy: let the function write to any list of Writes. On the real server the list is made of TcpStreams, in a test of Vec<u8> buffers:

fn yayinla<W: Write>(istemciler: &mut [W], gonderen: usize, mesaj: &str) {
    for (i, w) in istemciler.iter_mut().enumerate() {
        if i != gonderen {
            let _ = writeln!(w, "{mesaj}");   // a dropped client shouldn't stop everyone
        }
    }
}

In-memory testing

Since Vec<u8> implements Write, we can try the broadcast without a network:

let mut tamponlar: Vec<Vec<u8>> = vec![Vec::new(); 3];
yayinla(&mut tamponlar, 0, "ece: selam");
for (i, t) in tamponlar.iter().enumerate() {
    let metin = String::from_utf8_lossy(t);
    println!("{i}: {}", if metin.is_empty() { "-" } else { metin.trim() });
}

This is a small example of separating business logic from I/O (a sans-IO design).

Practice Broadcast

Write the generic yayinla function above. Broadcast the message ece: selam from sender 0 to three Vec<u8> buffers and print each buffer as i: content (- if empty).

Starter code

main.rs
use std::io::Write;

fn main() {
    // buraya yaz
}

Sample solution

main.rs
use std::io::Write;

fn yayinla<W: Write>(istemciler: &mut [W], gonderen: usize, mesaj: &str) {
    for (i, w) in istemciler.iter_mut().enumerate() {
        if i != gonderen {
            let _ = writeln!(w, "{mesaj}");
        }
    }
}

fn main() {
    let mut tamponlar: Vec<Vec<u8>> = vec![Vec::new(); 3];
    yayinla(&mut tamponlar, 0, "ece: selam");
    for (i, t) in tamponlar.iter().enumerate() {
        let metin = String::from_utf8_lossy(t);
        println!("{}: {}", i, if metin.is_empty() { "-" } else { metin.trim() });
    }
}

Expected output

0: -
1: ece: selam
2: ece: selam

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Why ignore the write error instead of propagating it with <code>?</code>?

  • The compiler forces it
  • It prevents others from missing the message because of one disconnected client Correct answer
  • Errors don't matter
  • Write returns no errors

Explanation: On a real server, clients failing to write are marked for removal from the list.

2 Except the sender

Question
for (i, w) in istemciler.iter_mut().enumerate() {
    if i ____ gonderen {
        let _ = writeln!(w, "{mesaj}");
    }
}
Answer
for (i, w) in istemciler.iter_mut().enumerate() {
    if i != gonderen {
        let _ = writeln!(w, "{mesaj}");
    }
}

Explanation: The message is written to everyone except the sender.

3 Client and what it receives (sender 0)

Term Meaning
0 -
1 ece: selam
writeln! error Ignored
Vec<u8> Implements Write

All lessons in Advanced