2014-11-01 3 views
1

Следующий код почти такой же, как в документации Rust для TcpListener. Когда код запущен на Ubuntu 14.04, он не производит никаких ошибок, но в то же время он не работает! (netstat -an | grep ':80' или telnet оба не подключаются к этому серверу).Rust TcpListener не удалось, но ошибок не было.

Если я сменил порт, он будет работать. Если я добавлю unwrap() после listen(), тогда код покажет «отказ в доступе». Я прочитал, что listen() возвращает IOResult<T>, и если он не используется, ошибки не будет. Но я думаю, что я использую его, вызывающий acceptor.incoming(), и я ожидаю ошибку при этом вызове. Почему этого не происходит?

Ржавчина версия: rustc 0.13.0-ночные (bd7138dd6 2014-10-27 23:02:55 +0000)

Ubuntu 14,04

fn main() { 
    let listener = TcpListener::bind("127.0.0.1", 80); 

    // bind the listener to the specified address 
    let mut acceptor = listener.listen(); //unwrap() here 

    fn handle_client(mut stream: TcpStream) { 
     println!("a"); 
    } 
    // accept connections and process them, spawning a new tasks for each one 
    for stream in acceptor.incoming() { 
     match stream { 
     Err(e) => { /* connection failed */ } 
     Ok(stream) => 
      spawn(proc() { 
       // connection succeeded 
       handle_client(stream) 
      }) 
     } 
    } 
    // close the socket server 
    drop(acceptor); 
} 
+0

Вы должны быть root для открытия привилегированных портов (<1024) – Arjan

+0

Я понял, что это не проблема для меня. Проблема в том, что программа не вводила никаких ошибок. –

+1

@FedorovMikhail заменить '/ * соединение не удалось * /' by 'println! (" {} ", E);' и вы увидите ошибки. – Levans

ответ

2

Существенным фактором является то, что Listener и Acceptor являются оба реализованы для IoResult<T>, где T реализует соответствующий признак. Вот отрывок из src/libstd/io/result.rs:

impl<T, A: Acceptor<T>, L: Listener<T, A>> Listener<T, A> for IoResult<L> { 
    fn listen(self) -> IoResult<A> { 
     match self { 
      Ok(listener) => listener.listen(), 
      Err(e) => Err(e), 
     } 
    } 
} 

impl<T, A: Acceptor<T>> Acceptor<T> for IoResult<A> { 
    fn accept(&mut self) -> IoResult<T> { 
     match *self { 
      Ok(ref mut acceptor) => acceptor.accept(), 
      Err(ref e) => Err(e.clone()), 
     } 
    } 
} 

Таким образом, TcpListener::bind возвращает IoResult<TcpListener>, который вы можете немедленно вызвать .listen() на; .listen() аналогичным образом возвращает IoResult<TcpAcceptor> и Acceptor, поэтому, когда вы вызываете .incoming(), вы получаете то, что всегда будет, и сразу же получите ошибки связывания или прослушивания, если они потерпят неудачу.