Skip to content

Instantly share code, notes, and snippets.

@ssrlive
Last active September 8, 2023 08:02
Show Gist options
  • Save ssrlive/45aaea6e80c32a1f31260bb1264896fb to your computer and use it in GitHub Desktop.
Save ssrlive/45aaea6e80c32a1f31260bb1264896fb to your computer and use it in GitHub Desktop.
Mio demo with rust
// [dependencies]
// mio = { version = "0.8", features = ["net", "os-ext", "os-poll"] }
use mio::{
event::Event,
net::{TcpListener, TcpStream},
Events, Interest, Poll, Token,
};
use std::{cell::RefCell, collections::HashMap, io::Read, net::SocketAddr, rc::Rc};
const SERVER: Token = Token(0);
struct MyServer {
listener: TcpListener,
connections: HashMap<Token, TcpStream>,
event_loop: Rc<RefCell<Poll>>,
last_token: usize,
}
#[derive(Debug)]
pub struct SErr(pub &'static str);
impl std::fmt::Display for SErr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.0, f)
}
}
impl std::error::Error for SErr {}
impl MyServer {
fn new(listener: TcpListener, event_loop: Rc<RefCell<Poll>>) -> MyServer {
MyServer {
listener,
connections: HashMap::new(),
event_loop,
last_token: SERVER.0,
}
}
fn new_token(&mut self) -> Token {
self.last_token += 1;
Token(self.last_token)
}
fn handle_event(&mut self, event: &Event) -> Result<(), Box<dyn std::error::Error>> {
match event.token() {
SERVER => {
// 有新連接進來
loop {
match self.listener.accept() {
Ok((mut stream, _)) => {
let token = self.new_token();
println!("New connection from: {}", stream.peer_addr()?);
self.event_loop
.borrow_mut()
.registry()
.register(&mut stream, token, Interest::READABLE)?;
self.connections.insert(token, stream);
}
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => return Ok(()),
Err(e) => return Err(e.into()),
}
}
}
token => {
// 有數據可讀
let mut buffer = [0; 1024];
loop {
match self.connections.get_mut(&token).ok_or(SErr("error"))?.read(&mut buffer) {
Ok(0) => {
// 客戶端斷開連接
println!("Connection closed: {:?}", self.connections[&token].peer_addr()?);
let mut stream = self.connections.remove(&token).ok_or(SErr("Connection not found"))?;
self.event_loop.borrow_mut().registry().deregister(&mut stream)?;
return Ok(());
}
Ok(n) => {
// 輸出收到的數據
let data = String::from_utf8_lossy(&buffer[..n]);
println!("Received data from {}: {}", self.connections[&token].peer_addr()?, data);
}
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => return Ok(()),
Err(e) => return Err(e.into()),
}
}
}
}
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 建立事件循環
let event_loop = Rc::new(RefCell::new(Poll::new()?));
// 建立 TCP 監聽器
let address = "127.0.0.1:8080".parse::<SocketAddr>()?;
let mut listener = TcpListener::bind(address)?;
event_loop
.borrow_mut()
.registry()
.register(&mut listener, SERVER, Interest::READABLE)?;
let mut my_server = MyServer::new(listener, event_loop.clone());
println!("Server listening on {}", address);
let mut events = Events::with_capacity(1024);
loop {
if let Err(err) = event_loop.borrow_mut().poll(&mut events, None) {
if err.kind() == std::io::ErrorKind::Interrupted {
continue;
}
return Err(err.into());
}
println!("new event");
for event in &events {
my_server.handle_event(event)?;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment