-
Notifications
You must be signed in to change notification settings - Fork 343
Open
@fvacek
Description
Documentation
Async chat server example is using connection_writer_loop()
task to ensure, that client messages will not be interleaved. https://book.async.rs/tutorial/sending_messages
What if broker_loop()
will send client messages back to connection_loop()
instead of creating connection_writer_loop()
and passing Acr<TcpStram>
all around? This can IMO lead to cleaner design, what is always good in tutorial. Also Acr<TcpStram>
is not necessary then, because TcpStream never escapes connection_loop()
. We can also use let (socket_reader, mut socket_writer) = (&stream, &stream);
pattern here.
We can then write something like this:
async fn connection_loop(client_id: i32, broker: Sender<ClientEvent>, stream: TcpStream) -> Result<()> { let (socket_reader, mut socket_writer) = (&stream, &stream); let reader = BufReader::new(socket_reader); let mut lines = reader.lines(); let name = match lines.next().await { None => Err("peer disconnected immediately")?, Some(line) => line?, }; broker.send(Event::NewPeer { name: name.clone(), stream: Arc::clone(&stream) }).await // 3 .unwrap(); let (peer_sender, peer_receiver) = channel::unbounded::<String>(); broker .send(ClientEvent::NewPeer { client_id, sender: peer_sender, }) .await .unwrap(); loop { select! { line = lines.next().fuse() => { let line = line?; let (dest, msg) = match line.find(':') { None => continue, Some(idx) => (&line[..idx], line[idx + 1 ..].trim()), }; let dest: Vec<String> = dest.split(',').map(|name| name.trim().to_string()).collect(); let msg: String = msg.to_string(); broker.send(Event::Message { // 4 from: name.clone(), to: dest, msg, }).await.unwrap(); }, message = peer_receiver.next().fuse() => match message { None => { break; } Some(message) => { socket_writer.send(msg.as_bytes()).await?; } } } } broker.send(ClientEvent::PeerGone { client_id }).await.unwrap(); Ok(()) }
Metadata
Metadata
Assignees
Labels
No labels