I am a beginner who has just started learning Rust language for two months. If the question I'm asking seems a bit foolish, please don't mock me.
I am using the tokio-modbus library to implement Modbus TCP。
When I call the tcp:: connect
method to asynchronously connect to the specified address socketaddr
. Store the returned connection object in the ctx
variable. I can use unwarp()
like this:
let mut ctx = tcp::connect(socket_addr).await.unwrap();
But if I use ?
, it will give an error like this:
let mut ctx = tcp::connect(socket_addr).await?;
The error is as follows:
the
?
operator can only be used in an async block that returnsResult
orOption
(or another type that implementsFromResidual
) the traitFromResidual<Result<Infallible, std::io::Error>>
is not implemented for()
This is the code for my entire function:
async fn client_context(socket_addr: SocketAddr) {
tokio::join!{
async {
// Give the server some time for starting up
tokio::time::sleep(Duration::from_secs(1)).await;// 等待1秒,确保服务器启动完成
println!("CLIENT: Connecting client...");
// 建立连接
// 通过调用tcp::connect
方法异步地连接到指定地址'socket_addr'。将返回的连接对象存储在ctx
变量中
let mut ctx = tcp::connect(socket_addr).await?;
println!("CLIENT: Reading 2 input registers...");
// 读取输入寄存器
// 从服务器读取起始地址为0x00
的2个输入寄存器
let response = ctx.read_input_registers(0x00, 2).await.unwrap();
println!("CLIENT: The result is '{response:?}'");
assert_eq!(response.unwrap(), vec![1234, 5678]);
println!("CLIENT: Writing 2 holding registers...");
// 写入寄存器
// 从起始地址为'0x01'写入[7777,8888]两个数据
ctx.write_multiple_registers(0x01, &[7777, 8888]).await;
// Read back a block including the two registers we wrote.
println!("CLIENT: Reading 4 holding registers...");
// 读取保持寄存器
// 从服务器读取起始地址为0x01
的4个保持寄存器
let response = ctx.read_holding_registers(0x00, 4).await.unwrap();
println!("CLIENT: The result is '{response:?}'");
assert_eq!(response.unwrap(), vec![10, 7777, 8888, 40]);
// 读取无效地址
println!("CLIENT: Reading nonexistent holding register address... (should return IllegalDataAddress)");
let response = ctx.read_holding_registers(0x100, 1).await.unwrap();
println!("CLIENT: The result is '{response:?}'");
assert!(matches!(response, Err(Exception::IllegalDataAddress)));
println!("CLIENT: Done.")
},
tokio::time::sleep(Duration::from_secs(5))
};
}