我似乎在与std::io::TcpStream做斗争.实际上,我正在try 打开与另一个系统的TCP连接,但下面的代码正好模拟了这个问题.

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

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

客户端所做的只是try 从连接中读取一个字节并打印它.

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连接很长一段时间,并在客户端和服务器之间来回发送消息.我在这里误解了什么?我与我正在通信的真实系统有着完全相同的问题——我只有在断开连接后才能解锁.

推荐答案

不幸的是,Rust现在没有任何异步I/O功能.有are多人试图纠正这种情况,但还远远没有完成.也就是说,人们希望实现真正的异步I/O(提议包括同时 Select 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秒内,插座上没有可用数据,recv_from将返回IoErrorkind设置为TimedOut.你需要在每次循环迭代之前重置超时,因为它更像是一个"截止日期",而不是一个超时——当它过期时,所有调用都将开始失败,并出现超时错误.

这绝对不是应该的方式,但Rust 目前并不能提供更好的效果.至少它做了它的工作.

Update

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

Rust相关问答推荐

将JSON密钥转换为Polars DataFrame

在没有引用计数或互斥锁的情况下,可以从Rust回调函数内的封闭作用域访问变量吗?

这种获取-释放关系是如何运作的?

铁 rust ,我的模块介绍突然遇到了一个问题

AXUM一路由多个不包括URL的参数类型

如何使用reqwest进行异步请求?

使用 pyo3 将 Rust 转换为 Python 自定义类型

write_buffer 不写入缓冲区而是输出零 WGPU

为什么某些类型参数仅在特征边界中使用的代码在没有 PhantomData 的情况下进行编译?

std mpsc 发送者通道在闭包中使用时关闭

Rust 中多个 & 符号的内存表示

如何从borrow 的异步代码运行阻塞代码?

返回优化后的标题:返回异步块的闭包的类型擦除

按下 Ctrl + C 时优雅地停止命令并退出进程

分配给下划线模式时会发生什么?

相交着色器从 SSBO 中读取零

如何用另一个变量向量置换 rust simd 向量?

返回引用的返回函数

为什么我返回的 impl Trait 的生命周期限制在其输入的生命周期内?

如何从 Rust 函数返回数组而不复制它们?