Rust mio 初探 ——echo server

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!(),
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值