Advance your echo server to a telnet based chat! Your chat server…
- Accepts multiple connections
- Broadcasts every message to all available connections Stretch goals
- Make sure you don't broadcast your message to yourself
| use std::{net::SocketAddr, future::Future, task::Poll, time::{Instant, Duration}}; | |
| use tokio::{ | |
| io::{AsyncBufReadExt, AsyncWriteExt, BufReader}, | |
| net::TcpListener, | |
| sync::broadcast, | |
| }; | |
| #[tokio::main] | |
| async fn main() -> tokio::io::Result<()> { | |
| let listener = TcpListener::bind("localhost:8001").await?; | |
| let (tx, _rx) = broadcast::channel::<(SocketAddr, String)>(100); | |
| loop { | |
| let (mut socket, addr) = listener.accept().await?; | |
| println!("Listening to {}", addr); | |
| let tx = tx.clone(); | |
| let mut rx = tx.subscribe(); | |
| tokio::spawn(async move { | |
| let (reader, mut writer) = socket.split(); | |
| let mut reader = BufReader::new(reader); | |
| loop { | |
| let mut buffer = String::new(); | |
| tokio::select! { | |
| // Reads from Channel, Sends to Socket | |
| msg = rx.recv() => { | |
| let (other_addr, msg) = msg.unwrap(); | |
| if other_addr != addr { | |
| writer.write_all(format!("{}: {}", other_addr, msg).as_bytes()).await.unwrap(); | |
| } | |
| } | |
| // Reads from Socket, sends to Channel | |
| result = reader.read_line(&mut buffer) => { | |
| if result.is_err() || buffer.trim() == "exit" { | |
| println!("Disconnected, {}", addr); | |
| break; | |
| } | |
| tx.send((addr, buffer)).unwrap(); | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| } |
| use std::{net::SocketAddr, future::Future, task::Poll, time::{Instant, Duration}}; | |
| use tokio::{ | |
| io::{AsyncBufReadExt, AsyncWriteExt, BufReader}, | |
| net::TcpListener, | |
| sync::broadcast, | |
| }; | |
| #[tokio::main] | |
| async fn main() -> tokio::io::Result<()> { | |
| loop { | |
| tokio::select! { | |
| a = MyFuture{} => { | |
| println!("First branch, {:?}", a); | |
| } | |
| b = MyFuture{} => { | |
| println!("Second branch, {:?}", b); | |
| } | |
| } | |
| tokio::time::sleep(Duration::from_millis(1000)).await; | |
| } | |
| } | |
| struct MyFuture; | |
| impl Future for MyFuture { | |
| type Output = Instant; | |
| fn poll(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> std::task::Poll<Self::Output> { | |
| let instant = Instant::now(); | |
| println!("From Future: {:?}", instant); | |
| Poll::Ready(instant) | |
| } | |
| } |
| use tokio::{ | |
| io::{AsyncWriteExt, BufReader, AsyncBufReadExt}, | |
| net::TcpListener, | |
| }; | |
| #[tokio::main] | |
| async fn main() -> tokio::io::Result<()> { | |
| let listener = TcpListener::bind("localhost:8001").await?; | |
| loop { | |
| let (mut socket, addr) = listener.accept().await?; | |
| println!("Listening to {}", addr); | |
| tokio::spawn(async move { | |
| loop { | |
| let (reader, mut writer) = socket.split(); | |
| let mut reader = BufReader::new(reader); | |
| let mut buffer = String::new(); | |
| if reader.read_line(&mut buffer).await.is_err() || buffer.trim() == "exit" { | |
| println!("Disconnected, {}", addr); | |
| break; | |
| } | |
| writer.write_all(buffer.as_bytes()).await.unwrap(); | |
| } | |
| }); | |
| } | |
| } | |
| use tokio::{ | |
| io::{self, AsyncWriteExt}, | |
| net::TcpListener, | |
| }; | |
| #[tokio::main] | |
| async fn main() -> io::Result<()> { | |
| let listener = TcpListener::bind("localhost:8001").await?; | |
| loop { | |
| let (mut socket, addr) = listener.accept().await?; | |
| println!("Listening to {}", addr); | |
| tokio::spawn(async move { socket.write_all("Hello World!\n\r".as_bytes()).await }); | |
| } | |
| } |