The following code should accept tcp connection, read from them, and close them on hangup.
extern crate mio;
use mio::{EventLoop,Token,ReadHint};
use mio::tcp::{TcpListener, TcpStream};
use std::io::Read;
const L_CLIENT: Token = Token(0);
const C_CLIENT: Token = Token(1);
fn sa(port:u16) -> std::net::SocketAddr {
let ipa : std::net::Ipv4Addr = std::net::Ipv4Addr::new(127,0,0,1);
std::net::SocketAddr::V4(std::net::SocketAddrV4::new(ipa,port))
}
fn main(){
let mut event_loop = EventLoop::new().unwrap();
let lclient = TcpListener::bind(&sa(4000)).unwrap();
event_loop.register(&lclient, L_CLIENT).unwrap();
println!("running loop...");
event_loop.run(&mut MyHandler{lclient:lclient,cclient:None}).unwrap();
println!("done.");
}
struct MyHandler{
lclient:TcpListener,
cclient:Option<TcpStream>,
}
impl mio::Handler for MyHandler {
type Timeout = ();
type Message = ();
fn readable(&mut self, event_loop: &mut EventLoop<Self>, token: Token, hint: ReadHint){
match token {
L_CLIENT => {
let s=self.lclient.accept().unwrap().expect("no client??");
match self.cclient{
None => {event_loop.register(&s,C_CLIENT);self.cclient=Some(s);}
Some(_) =>{println!("ignore second client");} // s should be closed as it goes out of scope
}
},
C_CLIENT => {
let mut client=self.cclient.expect("connection is gone"); // what's the problem here?
if hint.is_hup() {
event_loop.deregister(&client);
self.cclient=None; // how to close connection?
} else {
let mut buf: [u8; 500] = [0; 500];
let l=client.read(&mut buf).unwrap();
println!("read {} bytes.",l);
}
},
_ =>{println!("other Token");}
}
}
}
This almost works. In the C_CLIENT case I want to handle a client hangup. In that case I guess I need to move ownership for the connection from my handler to the method in order to let it go out of scope to close it.
Unfortunately rust will not allow me to move the connection:
error: cannot move out of borrowed content
As far as I understand the problem is that &self
is borrowed in the readable
method and therefore is not able to access its fields.
How do I access the connection? (avoiding the above error.)
How do I close that connection? (i.e. transfer ownership.)