rust - 如何将串行端口数据读入动态大小的缓冲区?
问题描述
我将此方法用作 WebSocket 客户端实现的一部分,以从串行端口读取数据并将其发送到服务器。我必须封装端口,Arc<Mutex<_>>
因为我需要与其他方法共享它,以便在接收到 WebSocket 消息时写入串行端口。
我使用 128 字节u8
的缓冲区来存储数据;有没有办法让缓冲区动态调整大小?包裹Arc<Mutex<_>>
是必须的。
extern crate env_logger;
extern crate ws;
use std::thread;
use ws::{listen, CloseCode, Handler, Handshake, Message, Result, Sender};
fn on_open(&mut self, _: Handshake) -> Result<(), ws::Error> {
let port_handle: Arc<Mutex<SystemPort>> = self.port_handle.clone();
let out: Sender = self.out.clone();
thread::spawn(move || {
// read_from_serial(&mut port);
let mut buffer = [0u8; 128];
let mut msg: String;
loop {
let read_result: Result<usize, std::io::Error>;
{
read_result = port_handle
.lock()
.expect("Access port handle")
.read(&mut buffer);
}
if read_result.is_ok() {
msg = buffer_to_string(&buffer);
buffer = [0u8; 128];
println!("Client sending message: '{}'", msg);
out.send(msg).expect("Forward COM message to server");
}
}
});
Ok(())
}
编辑:这是使用 read_to_string 而不是 read 的相同代码。字符串长度是完全动态的,但唯一的问题是 read_result 总是 Err(Custom { kind: TimedOut, error: StringError("Operation timed out") }) 这里。作为临时修复,我决定不使用 Result 并使用 msg.len() > 0 来测试新的串行消息。
extern crate env_logger;
extern crate ws;
use std::thread;
use ws::{listen, CloseCode, Handler, Handshake, Message, Result, Sender};
fn on_open(&mut self, _: Handshake) -> Result<(), ws::Error> {
let port_handle = self.port_handle.clone();
let out = self.out.clone();
thread::spawn(move || {
// read_from_serial(&mut port);
let mut buffer = String::new();
let mut msg;
loop {
{
port_handle
.lock()
.expect("Access port handle")
.read_to_string(&mut buffer);
msg = format!("{}", buffer);
}
if msg.len() > 0 {
buffer.clear();
println!("Client sending message: '{}'", msg);
out.send(msg).expect("Forward COM message to server");
}
}
});
Ok(())
}
编辑:我已经包含了以下最小示例并删除了所有其他不必要的代码。
extern crate env_logger;
extern crate serial;
use serial::prelude::*;
use std::io::Read;
use std::thread;
use std::time::Duration;
fn main() {
let client = thread::spawn(move || {
// setting up serial port
let mut port = serial::open("/dev/tnt0").expect("Open serial port");
let new_timeout = Duration::from_millis(1000);
port.set_timeout(new_timeout).expect("Set port timeout");
// setting up buffer
let mut buffer = String::new();
// looping to continuously read serial data
loop {
// unused Result returned by read_to_string
// because when used, it always is an Err variant
// `Custom { kind: TimedOut, error: StringError("Operation timed out") }`
port.read_to_string(&mut buffer);
// using string length to test for valid data instead of using Ok/Err
if buffer.len() > 0 {
println!("Client sending message: '{}'", buffer);
// clearing buffer for next iteration
buffer.clear();
}
}
});
// Wait for the worker threads to finish what they are doing
let _ = client.join();
println!("All done.")
}
解决方案
推荐阅读
- jenkins - 如何在詹金斯管道中访问 git commit 消息 INSIDE sh STEP?
- c - 给定一个矩阵和一些规则,设置二进制矩阵的所有位所需的最少天数是多少
- javascript - 在 jQuery 中几秒钟后显示和隐藏 div
- r - 软件包“jpeg”的安装具有非零退出状态
- spring - 使用 Spring Boot 运行 Spring Integration RSocket 示例时出错
- angular - ngrx - 将操作汇总到“流程”
- c++ - 只有第一个缓冲区在用 C++ 实现的双缓冲区中工作
- django - 如何在 wagtail 管理员之外上传文件
- rxjs - [Rxjs]如何在Rxjs中对多个同步事件进行分组,只触发一次订阅者?
- android - 为什么在android动态调试中文件偏移量不同