【问题标题】:How to exchange data in a block_on section?如何在 block_on 部分交换数据?
【发布时间】:2020-10-26 10:49:09
【问题描述】:

我正在学习 Rust 和 Tokio,我怀疑我可能走错了方向。

我正在尝试打开与远程服务器的连接并执行握手。我想使用非阻塞 IO,所以我使用 Tokio 的线程池。握手需要快速执行,否则遥控器将关闭套接字,因此我尝试将消息交换链接在单个 block_on 部分中:

let result: Result<(), Box<dyn std::error::Error>> = session
    .runtime()
    .borrow_mut()
    .block_on(async {
        let startup = startup(session.configuration());
        stream.write_all(startup.as_ref()).await?;

        let mut buffer:Vec<u8> = Vec::new();
        let mut tmp = [0u8; 1];
        loop {
            let total = stream.read(&mut tmp).await;
            /*
            if total == 0 {
                break;
            }
            */
            if total.is_err() {
                break;
            }
            buffer.extend(&tmp);
        }
        Ok(())
    });

我的问题是当套接字中没有更多字节要读取时该怎么办。我当前的实现读取响应并在最后一个字节挂起后,我相信是因为套接字没有关闭。我认为检查读取的 0 字节就足够了,但是对 read() 的调用永远不会返回。

最好的处理方法是什么?

【问题讨论】:

  • 您的客户端在完成发送数据后是否关闭套接字?
  • 不,连接应该保持打开状态。
  • 那是你的问题。 read 将永远阻塞等待更多数据,类似于您在 C 中执行非阻塞 read。您必须在代码中检测何时退出循环。
  • 有没有办法检查套接字中还剩下多少数据?
  • 没有?客户可以随时发送更多。如果你需要一个持久连接,你还需要一个框架协议,当一个请求停止而另一个请求开始时,它会告诉客户端和服务器。

标签: rust rust-tokio


【解决方案1】:

来自您的评论:

不,连接应该保持打开状态。

如果您从打开的连接读取,读取将阻塞,直到有足够的字节来满足它或另一端关闭连接,类似于 C 中阻塞读取的工作方式。Tokio 正在按预期工作。

如果关闭流并不表示消息结束,那么您将不得不自行确定何时停止读取并开始处理。一种简单的方法是在请求前面加上一个长度,然后只读取那么多字节。

请注意,无论您使用什么 API,都必须执行上述操作。您是否使用 tokio 并不能真正回答“消息何时结束”的基本问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 2011-07-07
    • 2021-10-31
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    • 2018-06-03
    相关资源
    最近更新 更多