如何在block_on节中交换数据?

问题描述

我正在学习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()的调用再也不会返回。

处理此问题的最佳方法是什么?

解决方法

根据您的评论

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

如果您从打开的连接中读取数据,则读取将一直阻塞,直到有足够的字节满足该请求,或者另一端关闭连接为止,类似于阻塞读取在C语言中的工作方式。Tokio按预期工作。

如果关闭流并不表示消息已结束,那么您将必须做自己的工作来弄清楚何时停止阅读并开始处理。一种简单的方法是在请求前加上一个长度,然后只读取那么多字节。

请注意,无论您使用哪种API,都必须执行上述操作。是否使用tokio的事实并不能真正回答“消息何时传递”这一基本问题。