rust中的超时处理

打印 上一主题 下一主题

主题 854|帖子 854|积分 2562

自从 tokio 1.0发布以来,rust的异步开发总算大势已定。尽管没达到标准库的速度,依然挡不住大家的热情。看编程排行榜,增加2倍的开发者。
既生瑜何生亮,感觉go就是小号的rust。
 
不废话了。背景:之前用go开发一个边缘网关的小东东,业余时间做了一大半。后来学了rust,打算练手,用rust重新写。
在crate中央仓库里找来找去,选择了 tokio-modbus。测试中发现用rtu的方式下,如果slave没有发回数据,程序将陷入无限等待中。也没找到如何设置这个超时。串口配置中倒是有个超时设置,不知道有啥用。
在tokio-modbus的github上,找到有人提到这个问题。那个解决问题的方式实在是理解不了,也很啰嗦。
自己动手, 用golang和tokio中都有的 select 很好的解决问题。
核心代码如下
  1. 1 tokio::select! {
  2. 2     result = &ctx.read_holding_registers(3,12) => match result {
  3. 3         Ok(v) => println!("Reading holding {:?}", v),
  4. 4         Err(_) => println!("reading err"),
  5. 5     },
  6. 6     _ = tokio::time::sleep(std::time::Duration::from_millis(100)) => println!("reading timeout 100 ms"),
  7. 7 }
复制代码
完整的测试代码如下
  1. use tokio_modbus::prelude::Reader;
  2. use tokio_serial::SerialPortBuilderExt;
  3. #[tokio::main]
  4. async fn main() -> Result<(), Box<dyn std::error::Error>> {
  5.     let mut port = String::from("");
  6.     let ports = tokio_serial::available_ports().unwrap();
  7.     for p in ports {
  8.         port = String::from("com1");
  9.         match p.port_type {
  10.             tokio_serial::SerialPortType::UsbPort(info) => {
  11.                 println!("{}, {:?}", p.port_name, info);
  12.                 port = p.port_name;
  13.             },
  14.             _ => println!("{}, unknown type", p.port_name),
  15.         }
  16.     }
  17.     println!("port is {}", port);
  18.     let slave = tokio_modbus::slave::Slave(0x3);
  19.     let com = tokio_serial::new(port,9600)
  20.         .timeout(std::time::Duration::from_millis(70))
  21.         .data_bits(tokio_serial::DataBits::Eight)
  22.         .stop_bits(tokio_serial::StopBits::One)
  23.         .parity(tokio_serial::Parity::None)
  24.         .open_native_async();  // tokio_serial::SerialPortBuilderExt
  25.     // let com = tokio_serial::SerialStream::open(&builder).unwrap();
  26.     // only open local serial_port
  27.     let ctx = tokio_modbus::prelude::rtu::connect_slave(com.unwrap(), slave).await;
  28.     let mut ctx = match ctx {
  29.         Ok(c) => c,
  30.         Err(e) => { println!("err is {}", e); return Ok(())},
  31.     };
  32.     println!("rtu ctx ok, {:?}", ctx);
  33.     let now = std::time::Instant::now();
  34.     // let mut timeend = tokio::time::sleep(std::time::Duration::from_millis(100));
  35.     tokio::select! {
  36.         result = &ctx.read_holding_registers(3,12) => match result {
  37.             Ok(v) => println!("Reading holding {:?}", v),
  38.             Err(_) => println!("reading err"),
  39.         },
  40.         _ = tokio::time::sleep(std::time::Duration::from_millis(100)) => println!("reading timeout 100 ms"),
  41.     }
  42.     println!("elapsed {} millis", now.elapsed().as_millis());
  43.     Ok(())
  44. }
复制代码
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

惊落一身雪

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表