Зарегистрировать канал с помощью mio - PullRequest
2 голосов
/ 26 апреля 2019

В старых версиях mio doc я нахожу mio :: channel, который, по-видимому, использовался для создания канала, реализующего EventedFd, который можно зарегистрировать с помощью Poll. Я также вижу на Reddit, что это было изменено в пользу чего-то другого, но я не могу понять, каков новый способ регистрации канала.

Каков текущий способ ожидания даты на канале (std::sync::mpsc или что-то еще) с mio? Все, что я могу найти в Google, это ссылки на старые версии Mio Docs. Спасибо!

Поскольку я столкнулся с той же проблемой, я надеюсь, что все в порядке, я предоставляю некоторый код, чтобы облегчить понимание вопроса:

use std::io;
use std::net::*; //{TcpListener,TcpStream,IpAddr,Ipv4Addr,SocketAddr};
use std::thread::*;
use std::sync::mpsc::*; //{Receiver,SyncSender,Sender,channel,sync_channel};

fn poll_quit( rx : &Receiver::<u8> ) -> bool {
    match rx.try_recv() {
        Ok(_) => true,
        Err(TryRecvError::Empty) => false,
        Err(TryRecvError::Disconnected) => true
    }
}

fn guard_external_tcp_port( rx : Receiver::<u8>) -> () {
    let listener = TcpListener::bind("127.0.0.1:8384").expect("tcp guard - bind failed!");
    listener.set_nonblocking(true).expect("cannot set tcp listener to nonblocking!");
    while false == poll_quit(&rx) {
        match listener.accept() {
            Ok((_s,pa)) => {
                println!("tcp client connected: {} - closing it down."
                    , pa);
            }
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                //wait_for_fd();
                continue;
            }
            Err(e) => panic!("encountered IO error: {}", e),

        }
    }
}

fn start_tcpguard() -> (JoinHandle<()>,SyncSender::<u8>) {
    let (tx,rx) = sync_channel::<u8>(0);
    let thrd = spawn(move || {
        guard_external_tcp_port(rx);
    });
    (thrd,tx)
}

До этого момента я пытался обойтись без mio, но проблема очевидна: вы хотите заблокировать, пока не поступит сообщение канала отключения или пока не будет сигнализирован сокет слушателя. Достаточно стимула перейти на мио. Если только Мио не сможет ждать Receiver.

1 Ответ

1 голос
/ 02 мая 2019

Существует еще один mio-ящик, который имеет функции, связанные с каналом:

mio-extras

Итак, все, что вам нужно сделать, это добавить, чтоЯщик к вашему cargo.toml [dependencies].
Затем, в вашем main.rs, добавьте extern crate mio_extras, и у вас должно быть все это готово к использованию.

Итак, в случае моего фрагмента кодаЯ добавил к вопросу, в конечном итоге это выглядит так:

extern crate mio;
extern crate mio_extras;

use std::io;
use mio::*;
use mio::net::*;
use mio_extras::channel::*;
use std::thread::*;

fn guard_external_tcp_port( rx : mio_extras::channel::Receiver::<u8>) -> () {
    let poll = Poll::new().expect("could not create a new Poll instance.");
    const QUIT : Token = Token(0);
    const CONNECT : Token = Token(1);


    let mut events = Events::with_capacity(5);
    poll.register(&rx,QUIT,Ready::readable(),PollOpt::level() ).expect("could not register channel Receiver.");


    let addr : std::net::SocketAddr = "127.0.0.1:8384".parse().unwrap();
    let listener = TcpListener::bind(&addr).expect("tcp guard - bind failed!");

    poll.register(&listener,CONNECT,Ready::all(),PollOpt::edge()).expect("could not register our listening socket.");

    let mut running : bool = true;
    //listener.set_nonblocking(true).expect("cannot set tcp listener to nonblocking!");
    while running {
        let _nevents = poll.poll(&mut events,None).unwrap();
        println!("poll returned!");
        for event in &events {
            match event.token() {
                QUIT => running = false,
                CONNECT => {
                    match listener.accept() {
                        Ok((_s,pa)) => {
                            println!("tcp client connected: {} - closing it down."
                                , pa);
                        }
                        Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                            //wait_for_fd();
                            continue;
                        }
                        Err(e) => panic!("encountered IO error: {}", e),
                    }
                },
                Token(_) => continue
            }
        }
    }
}

fn start_tcpguard() -> (JoinHandle<()>,Sender::<u8>) {
    let (tx,rx) = mio_extras::channel::channel::<u8>();
    let thrd = spawn(move || {
        guard_external_tcp_port(rx);
    });
    (thrd,tx)
}

Я также попробовал версию sync_channel(0), и она не работает должным образом.Версия в приведенном выше коде, хотя и работает в отношении опроса, получающего событие завершения работы.

...