Rust持久性TcpStream

时间:2014-09-03 06:23:20

标签: 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 {}
}

所有客户端都尝试从连接中读取单个字节并将其打印出来。

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
        }
      }
    }
}

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

1 个答案:

答案 0 :(得分: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
}

如果在recv_from调用内5秒内套接字上没有可用数据,IoErrorkind设置为TimedOut,将返回recv_from。你需要在每次循环迭代之前重置超时,因为它更像是一个“截止日期”而不是超时 - 当它到期时,所有调用都会因超时错误而开始失败。

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

<强>更新

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