• rust中的超时处理


    自从 tokio 1.0发布以来,rust的异步开发总算大势已定。尽管没达到标准库的速度,依然挡不住大家的热情。看编程排行榜,增加2倍的开发者。

    既生瑜何生亮,感觉go就是小号的rust。

    不废话了。背景:之前用go开发一个边缘网关的小东东,业余时间做了一大半。后来学了rust,打算练手,用rust重新写。

    在crate中央仓库里找来找去,选择了 tokio-modbus。测试中发现用rtu的方式下,如果slave没有发回数据,程序将陷入无限等待中。也没找到如何设置这个超时。串口配置中倒是有个超时设置,不知道有啥用。

    在tokio-modbus的github上,找到有人提到这个问题。那个解决问题的方式实在是理解不了,也很啰嗦。

    自己动手, 用golang和tokio中都有的 select 很好的解决问题。

    核心代码如下

    1 tokio::select! {
    2     result = &ctx.read_holding_registers(3,12) => match result {
    3         Ok(v) => println!("Reading holding {:?}", v),
    4         Err(_) => println!("reading err"),
    5     },
    6     _ = tokio::time::sleep(std::time::Duration::from_millis(100)) => println!("reading timeout 100 ms"),
    7 }

    完整的测试代码如下

    use tokio_modbus::prelude::Reader;
    use tokio_serial::SerialPortBuilderExt;
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
    
        let mut port = String::from("");
    
        let ports = tokio_serial::available_ports().unwrap();
        for p in ports {
    
            port = String::from("com1");
    
            match p.port_type {
                tokio_serial::SerialPortType::UsbPort(info) => {
                    println!("{}, {:?}", p.port_name, info);
                    port = p.port_name;
                },
                _ => println!("{}, unknown type", p.port_name),
            }
    
        }
    
        println!("port is {}", port);
    
    
        let slave = tokio_modbus::slave::Slave(0x3);
        let com = tokio_serial::new(port,9600)
            .timeout(std::time::Duration::from_millis(70))
            .data_bits(tokio_serial::DataBits::Eight)
            .stop_bits(tokio_serial::StopBits::One)
            .parity(tokio_serial::Parity::None)
            .open_native_async();  // tokio_serial::SerialPortBuilderExt
    
        // let com = tokio_serial::SerialStream::open(&builder).unwrap();
    
        // only open local serial_port
        let ctx = tokio_modbus::prelude::rtu::connect_slave(com.unwrap(), slave).await;
    
        let mut ctx = match ctx {
            Ok(c) => c,
            Err(e) => { println!("err is {}", e); return Ok(())},
        };
    
        println!("rtu ctx ok, {:?}", ctx);
    
        let now = std::time::Instant::now();
    
        // let mut timeend = tokio::time::sleep(std::time::Duration::from_millis(100));
        tokio::select! {
            result = &ctx.read_holding_registers(3,12) => match result {
                Ok(v) => println!("Reading holding {:?}", v),
                Err(_) => println!("reading err"),
            },
            _ = tokio::time::sleep(std::time::Duration::from_millis(100)) => println!("reading timeout 100 ms"),
        }
    
        println!("elapsed {} millis", now.elapsed().as_millis());
        Ok(())
    }
  • 相关阅读:
    POJ-2253 Frogger dijsktra查找间隔最小的路径
    LightOJ-1282 Leading and Trailing 模算数 快速幂 对数的用法
    LightOJ-1341 Aladdin and the Flying Carpet 分解质因数(注意对大素数的优化)
    UVA-10200 Prime Time 素数(注意除法精度)
    POJ-2142 The Balance 扩展欧几里德(+绝对值和最小化)
    ArchLinux 音乐播放客户端ncmpcpp和服务端mpd的配置
    [笔记-统计学习方法]感知机模型(perceptron) 原理与实现
    [Bug]Python3.x AttributeError: libtest.so: undefined symbol: fact
    [Bug]C++ XXX:undefined reference to "xxx"
    ip代理池的爬虫编写、验证和维护
  • 原文地址:https://www.cnblogs.com/htsky/p/16395245.html
Copyright © 2020-2023  润新知