Rust
Kanal ile mesaj
mpsc ile mesajları toplayıp dağıtırsın.
Kanal ile mesaj
Sohbette istemci thread'leri gelen mesajları merkezi bir yere iletmelidir. Her istemci işleyicisine bir Sender kopyası verilir; merkezi thread tek Receiver'dan okur. Böylece ortak durum kilitlenmeden mesajlar tek bir sırada toplanır:
fn istemci_isle(akis: TcpStream, id: usize, tx: Sender<String>) -> io::Result<()> {
for s in BufReader::new(akis).lines() {
tx.send(format!("[{id}] {}", s?)).ok();
}
Ok(())
}
İstemci bağlantıyı kapatınca lines() biter, thread sonlanır ve göndericisi bırakılır.
Kabul döngüsünü bağlamak
Kabul eden thread, her bağlantıya artan bir kimlik ve göndericinin bir kopyasını verir:
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
for (id, akis) in dinleyici.incoming().take(2).enumerate() {
let tx = tx.clone();
let akis = akis.unwrap();
thread::spawn(move || istemci_isle(akis, id, tx));
}
// tx burada bırakılır
});
Gerçek bir sunucuda take olmaz; kapatma sinyali ayrı bir kanalla gönderilir.
Uygulama Merkeze ilet
Yukarıdaki istemci_isle ve kabul döngüsünü kur. Ana thread iki istemciyi sırayla bağlasın: biri selam, diğeri nasılsın yazıp bağlantıyı kapatsın. Ardından rx.iter() ile tüm mesajları topla, sırala ve her birini yazdır.
Örnek çözümü göster
use std::io::{self, BufRead, BufReader, Write};
use std::net::{TcpListener, TcpStream};
use std::sync::mpsc::{self, Sender};
use std::thread;
fn istemci_isle(akis: TcpStream, id: usize, tx: Sender<String>) -> io::Result<()> {
for s in BufReader::new(akis).lines() {
tx.send(format!("[{id}] {}", s?)).ok();
}
Ok(())
}
fn main() -> io::Result<()> {
let dinleyici = TcpListener::bind("127.0.0.1:0")?;
let adres = dinleyici.local_addr()?;
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
for (id, akis) in dinleyici.incoming().take(2).enumerate() {
let tx = tx.clone();
let akis = akis.unwrap();
thread::spawn(move || istemci_isle(akis, id, tx));
}
});
for mesaj in ["selam", "nasılsın"] {
let mut akis = TcpStream::connect(adres)?;
writeln!(akis, "{mesaj}")?;
}
let mut hepsi: Vec<String> = rx.iter().collect();
hepsi.sort();
for m in hepsi {
println!("{}", m);
}
Ok(())
}
Kendini test et
-
Merkezi alıcı ne zaman "tüm mesajlar geldi" diyebilir?
- Bir saniye sonra
- Hiçbir zaman
- Tüm göndericiler (her işleyicininki ve kabul döngüsününki) bırakıldığında
- İlk mesajda
Cevabı göster
Tüm göndericiler (her işleyicininki ve kabul döngüsününki) bırakıldığında — Kabul döngüsü kendi tx kopyasını tutuyorsa, döngü bitince onu da bırakmalıdır.
-
Göndericiyi ver
let tx = tx.____();
thread::spawn(move || istemci_isle(akis, id, tx));
Cevabı göster
let tx = tx.clone();
thread::spawn(move || istemci_isle(akis, id, tx));
-
Bileşen ve görevi
- Sender<String>
- İşleyiciden merkeze
- Receiver
- Merkezi okuyucu
- enumerate()
- İstemci kimliği
- lines() biter
- İstemci ayrıldı
Sıradaki ders: Broadcast