Rust持久性TcpStream

Upi*_*pio 7 sockets tcp rust

我似乎在与std :: io :: TcpStream挣扎.我实际上是尝试与另一个系统打开TCP连接,但下面的代码完全模拟了问题.

我有一个Tcp服务器,只需在打开时将"Hello World"写入TcpStream,然后循环以保持连接打开.

fn main() {
  let listener = io::TcpListener::bind("127.0.0.1", 8080);
  let mut acceptor = listener.listen();
  for stream in acceptor.incoming() {

    match stream {
      Err(_) => { /* connection failed */ }
      Ok(stream) => spawn(proc() {
        handle(stream);
      })
    }
  }
  drop(acceptor);
}

fn handle(mut stream: io::TcpStream) {
  stream.write(b"Hello Connection");
  loop {}
}
Run Code Online (Sandbox Code Playgroud)

所有客户端都尝试从连接读取单个字节并打印它.

fn main() {
    let mut socket = io::TcpStream::connect("127.0.0.1", 8080).unwrap();
    loop {
      match socket.read_byte() {
        Ok(i) => print!("{}", i),
        Err(e) => {
          println!("Error: {}", e);
          break
        }
      }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在的问题是我的客户端在读取时仍然被阻止,直到我终止服务器或关闭TCP连接.这不是我想要的,我需要打开TCP连接很长一段时间,并在客户端和服务器之间来回发送消息.我在这里误解了什么?我与我正在通信的真实系统有完全相同的问题 - 一旦我终止连接,我才会被解锁.

Vla*_*eev 7

不幸的是,Rust现在没有任何异步I/O工具.这里一些尝试,以纠正这种情况,但他们远远没有完成呢.也就是说,希望能够实现真正的异步I/O(提议包括同时选择I/O源和通道,这将允许唤醒通过I/O操作在I/O操作中被阻止的任务.虽然目前尚不清楚如何在所有支持的平台上实现这一点,但是还有很多工作要做,而且就我所知,现在没有什么可用的.

但是,您可以在一定程度上模拟这种超时.这远不是最好的解决方案,但它确实有效.它可能看起来像这样(我的代码库中的简化示例):

let mut socket = UdpSocket::bind(address).unwrap();

let mut buf = [0u8, ..MAX_BUF_LEN];
loop {
    socket.set_read_timeout(Some(5000));
    match socket.recv_from(buf) {
        Ok((amt, src)) => { /* handle successful read */ }
        Err(ref e) if e.kind == TimedOut => {}  // continue
        Err(e) => fail!("error receiving data: {}", e)  // bail out
    }

    // do other work, check exit flags, for example
}
Run Code Online (Sandbox Code Playgroud)

这里recv_from将返回IoErrorkind设置为TimedOut如果没有在5内部几秒钟内插座上的数据recv_from呼叫.你需要在每次循环迭代之前重置超时,因为它更像是一个"截止日期"而不是超时 - 当它到期时,所有调用都会因超时错误而开始失败.

这绝对不是它应该做的方式,但Rust目前没有提供更好的东西.至少它做了它的工作.

更新

现在尝试基于它创建异步事件循环和网络I/O. 它被称为mio.对于异步I/O,它可能是一个很好的临时(甚至永久,谁知道)解决方案.