mio
本篇博文错误百出谨慎阅读
mio一个隔离了windows上IOCP和linux上epoll的rust库,mio自带的test例子对初学者一点都不友好,我反正是看了半天不知道它要干什么。
,写了两个例子,分别是基于udp和tcp的echo-server
[dependencies]
mio = "0.6"
extern crate mio;
use std::collections::HashMap;
use std::io::*;
use mio::net::{TcpListener, TcpStream};
use mio::{Token, Poll, Ready, PollOpt, Events};
fn main() {
// Set up a token to identify the UDP socket can be read.
const SERVER: Token = Token(0);
let mut curr_client_id = 1;
let tcp_addr = "127.0.0.1:9000".parse().unwrap();
// Setup the server socket
let tcp_server = TcpListener::bind(&tcp_addr).unwrap();
// Create a poll instance
let poll = Poll::new().unwrap();
let pollopts = if cfg!(feature = "level") {
PollOpt::level()
} else {
if cfg!(feature = "oneshot") {
PollOpt::edge() | PollOpt::oneshot()
} else {
PollOpt::edge()
}
};
// Start listening for incoming connections
poll.register(&tcp_server, SERVER, Ready::readable(), PollOpt::edge())
.unwrap();
// Create storage for events
let mut events = Events::with_capacity(1024);
let buf = &mut [0u8; 1024];
let mut amt = 0;
let mut streams = HashMap::new();//只要流保存了,TCP连接就不关闭,根据客户端的id取流
loop {
poll.poll(&mut events, None).unwrap();
for event in events.iter() {
match event.token() {
SERVER => {
let (stream, _addr) = tcp_server.accept().unwrap();
let client_id = curr_client_id;
curr_client_id += 1;
let token = Token(client_id);
if let Some(_stream) = streams.insert(client_id, stream) {
panic!("Stream entry token filled.");
}
poll.register(&streams[&client_id], token, Ready::readable(), pollopts)
.unwrap();//为每一个新的TCP 客户端注册不同的token
}
Token(client_id) => {
if event.readiness().is_readable() {
let stream = streams.get_mut(&client_id).unwrap();
match stream.read(buf) {
Ok(nread) => {
amt = nread;
println!("Received {} Bytes", nread);
poll.reregister(
stream,
Token(client_id),
Ready::writable(),
pollopts,
).unwrap();//读完了 就开始准备写
}
Err(e) => println!("read err {}", e),
}
}
if event.readiness().is_writable() {
let mut stream = streams.remove(&client_id).unwrap();//移除流TCP在stream生命周期结束后主动关闭
match stream.write(&buf[..amt]) {
Ok(nwrite) => println!("write {} Bytes", nwrite),
Err(e) => println!("write err {}", e),
}
}
}
_ => unreachable!(),
}
}
}
}
extern crate mio;
use mio::*;
use std::str::FromStr;
use std::net::SocketAddr;
use mio::net::UdpSocket;
const SERVER_ADDR: &'static str = "127.0.0.1:9000";
const BUF_SIZE: usize = 1024;
const UDP_TOKEN: Token = Token(0);
fn main() {
let server_addr = SocketAddr::from_str(SERVER_ADDR).unwrap();
let sock = UdpSocket::bind(&server_addr).unwrap();
let poll = Poll::new().unwrap();
let mut events = Events::with_capacity(1024);
let pollopts = if cfg!(feature = "level") {
PollOpt::level()
} else {
if cfg!(feature = "oneshot") {
PollOpt::edge() | PollOpt::oneshot()
} else {
PollOpt::edge()
}
};
poll.register(&sock, UDP_TOKEN, Ready::readable(), pollopts)
.unwrap();
let buf = &mut [0u8; BUF_SIZE];
let mut address = None;
let mut amt = 0;
loop {
poll.poll(&mut events, None).unwrap();
for event in events.iter() {
match event.token() {
UDP_TOKEN => {
// read response from echo server
if event.readiness().is_readable() {
match sock.recv_from(buf) {
Ok((nread, addr)) => {
println!("{:?} [{}] => {:?}", addr, nread, &buf[..nread]);
amt = nread;
address = Some(addr);
poll.reregister(&sock, UDP_TOKEN, Ready::writable(), pollopts)
.unwrap();
}
Err(e) => println!("recv_from error: {}", e),
}
}
if event.readiness().is_writable() {
println!("{:?}", address);
match sock.send_to(&buf[..amt], &address.unwrap()) {
Ok(nwrite) => println!("writed {}/{}", nwrite, amt),
Err(e) => println!("send_to error {}", e),
}
poll.reregister(&sock, UDP_TOKEN, Ready::readable(), pollopts)
.unwrap();
}
}
_ => unreachable!(),
}
}
}
}