Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets 锈流_Sockets_Tcp_Rust - Fatal编程技术网

Sockets 锈流

Sockets 锈流,sockets,tcp,rust,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 acc

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

不幸的是,Rust现在没有任何异步I/O功能。有人试图纠正这种情况,但还远远没有完成。也就是说,人们希望实现真正的异步I/O(建议包括同时选择I/O源和通道,这将允许通过通道上的事件唤醒I/O操作中被阻塞的任务,尽管尚不清楚如何在所有受支持的平台上实现这一点),但就我所知,还有很多事情要做,现在没有什么真正有用的

但是,您可以在一定程度上通过超时来模拟这一点。这远不是最好的解决方案,但它是有效的。它可能如下所示(我的代码库中的简化示例):

如果在
recv\u from
调用的5秒内,插座上没有可用数据,则
recv\u from
将返回
IoError
,并将
kind
设置为
TimedOut
。您需要在每次循环迭代内部之前重置超时,因为它更像是一个“截止日期”,而不是一个超时-当它过期时,所有调用都将开始失败并出现超时错误

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

更新


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

好的,所以我将无法执行正确的异步I/O。。。真倒霉但是,为什么在连接关闭之前不能从TCP流读取数据?它是否实现了在EOF之前缓冲所有数据?@Upio,您不是说过:“现在的问题是,在我关闭服务器或TCP连接之前,我的客户端在读取时一直处于阻塞状态”?这是“从TCP流读取数据,直到连接关闭”,不是吗?无论如何,
TcpStream
是一个方法,因此它有一个方法,在关闭之前消耗所有流。这就是你需要的吗?对不起,如果我不清楚的话,我已经知道如何与读者互动了。我只想理解为什么在连接关闭之前,客户端不会读取任何数据。即使我使用read_byte(),它也会阻塞直到连接终止。这在内部是如何工作的?@Upio,但您希望它如何工作
read_byte()
尝试从连接中读取下一个字节;这归结为最低级别的
read()
系统调用,它将阻止当前线程,直到读取该字节或发生错误为止。发出无需读取的信号的唯一方法(没有异步I/O)是从写入端关闭连接,这将在读取端触发EOF“error”。套接字就是这样工作的。我希望从服务器发送的字节在发送后可用,而不是在连接关闭后可用。这就是我看到的行为。在关闭连接之前,我不会阻塞和读取任何数据。我认为它会读取发送的每个字节,打印到终端,然后阻塞直到连接关闭。我认为这需要一个更新的答案。
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
}