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 }); | |
} | |
} |