更新:这似乎更像是正确生成和信任自签名证书的问题
我正在使用 tokio-rs 构建服务器和客户端。我一切正常,但现在正在尝试将 SSL/TLS 添加到系统中。据我所知,我已经生成了一个自签名证书并正确安装了它,但是每次我尝试让客户端连接到服务器时,我都会收到以下错误:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Failure(Ssl(ErrorStack([Error { code: 336134278, library: "SSL routines", function: "ssl3_get_server_certificate", reason: "certificate verify failed", file: "s3_clnt.c", line: 1264 }])))', /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libcore/result.rs:837
Run Code Online (Sandbox Code Playgroud)
我正在使用以下脚本生成 crt、key 和 pfx 文件:
openssl req -nodes -x509 -newkey rsa:2048 -config ssl.conf -extensions ext -subj /C=CA/ST=EH/L=Canadia/O=Dis/CN=localhost -keyout localhost.key -out localhost.crt -days 365
openssl pkcs12 -export -nodes -inkey localhost.key -in localhost.crt -out localhost.pfx
mv localhost.pfx ../
Run Code Online (Sandbox Code Playgroud)
使用这个配置文件
[req]
distinguished_name=dn
[ dn ]
CN=localhost
[ ext …Run Code Online (Sandbox Code Playgroud) 将 Tokio (v 0.1.11)n线程池限制为OS 本机线程的正确方法是什么,其中n是任意数量,最好在运行时配置?
据我所知,可以使用 usingtokio_current_thread::block_on_all代替tokio::run和tokio_current_thread::spawn代替在单线程模式下使用 Tokiotokio::spawn。
我想要一个类似的解决方案,但对于n >= 1.
我想每秒打印一次“你好”。
引用文档:
期货使用基于投票的模型。未来的消费者反复调用 poll 函数。未来然后试图完成。如果未来能够完成,则返回 Async::Ready(value)。如果未来由于被内部资源(例如 TCP 套接字)阻塞而无法完成,则返回 Async::NotReady。
如果s return is ,我的poll函数返回,但没有任何内容打印到标准输出。NotReadyDelayNotReady
use futures::{Async, Future, Stream}; // 0.1.25
use std::time::{Duration, Instant};
use tokio::timer::Delay; // 0.1.15
struct SomeStream;
impl Stream for SomeStream {
type Item = String;
type Error = ();
fn poll(&mut self) -> Result<Async<Option<Self::Item>>, Self::Error> {
let when = Instant::now() + Duration::from_millis(1000);
let mut task = Delay::new(when).map_err(|e| eprintln!("{:?}", e));
match task.poll() {
Ok(Async::Ready(value)) => {}
Ok(Async::NotReady) => return Ok(Async::NotReady),
Err(err) => return Err(()), …Run Code Online (Sandbox Code Playgroud) 我有一个无法在编译时计算的值。它需要在任何应用程序代码运行之前进行计算,然后它只会在应用程序的整个生命周期中被读取。它还需要传递给执行者,例如处理程序tokio和hyper处理程序。
我怎样才能安全、惯用地创造这样的价值,并且不会造成不必要的性能损失?
main并将其传递给hyper,它的寿命就不够长。lazy_static!,则仅在首次访问时才计算它。如果无法计算,那么我也不想运行应用程序的其余部分。我宁愿知道在启动应用程序时无法连接到数据库,而不是在客户端发出请求时无法连接到数据库。static mut,那么我就无法在安全代码中使用它。理想情况下,我想做类似的事情:
#[tokio::main]
pub async fn main() {
let db = init_db();
// This uses a hyper server, passes db around
// to tokio and hyper handlers, etc.
run_app(&db);
}
Run Code Online (Sandbox Code Playgroud) tokio有一个合并数据结构,允许“合并”两个同构流并忘记出处。
impl<T, U> Stream for Merge<T, U> where
T: Stream,
U: Stream<Item = T::Item>, { ...
Run Code Online (Sandbox Code Playgroud)
是否存在流的代数逐点标记联合,它从 的流a和 的流b生成 的流Either a b?
PS:我想答案是否定的,因为 Rust 显然没有标准的总和类型。
我实现了 tonic helloworld教程。然后我尝试更改客户端代码,以便我可以在等待任何请求之前发送多个请求。
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let num_requests = 10;
let mut client = GreeterClient::connect("http://[::1]:50051").await?;
let mut responses = Vec::with_capacity(num_requests);
for _ in 0..num_requests {
let request = tonic::Request::new(HelloRequest {
name: "Tonic".into(),
});
responses.push(client.say_hello(request));
}
for resp in responses {
assert!(resp.await.is_ok());
}
Ok(())
}
Run Code Online (Sandbox Code Playgroud)
这会导致编译错误:
error[E0499]: cannot borrow `client` as mutable more than once at a time
--> src/client.rs:19:24
|
19 | responses.push(client.say_hello(request));
| ^^^^^^ mutable borrow starts here in previous iteration of …Run Code Online (Sandbox Code Playgroud) 我设置超时为1s,但是任务执行到3s,却没有发生panic。
#代码
#[should_panic]
fn test_timeout() {
let rt = create_runtime();
let timeout_duration = StdDuration::from_secs(1);
let sleep_duration = StdDuration::from_secs(3);
let _guard = rt.enter();
let timeout = time::timeout(timeout_duration, async {
log("timeout running");
thread::sleep(sleep_duration);
log("timeout finsihed");
"Ding!".to_string()
});
rt.block_on(timeout).unwrap();
}
Run Code Online (Sandbox Code Playgroud) 我想了解 Rust 中 tokio 的 async/await 线程模型。我特别想知道 async/await 何时会导致代码在不同线程上执行。
我观察到,在带async fn main注释的#[tokio::main](创建多线程运行时)中运行 async/await/join 代码会在同一线程中执行所有代码。在我开始通过 执行代码之前,我没有看到其他线程被使用tokio::spawn。
一些相关文档。
任务是调度程序管理的执行单元。生成任务会将其提交给 Tokio 调度程序,然后调度程序确保该任务在有工作要做时执行。生成的任务可以在生成它的同一线程上执行,也可以在不同的运行时线程上执行。任务生成后还可以在线程之间移动。(强调我的)
这表示生成的单个 tokio 任务可以在执行期间在线程之间移动。什么时候会发生这种情况?
还有block_on运行#[tokio::main]函数体的文档
这会在当前线程上运行给定的 future,阻塞直到完成,并产生其解析结果。future 内部产生的任何任务或计时器都将在运行时执行。
这可以理解为除非产生新的任务或计时器,否则给定未来的代码将全部在同一线程上运行。这是我观察到的。
异步 rust 代码是否会在.await连接调用中同时(但不是并行)进行 future,并且仅在tokio::spawn使用时安排在不同的线程上?
文档似乎另有说明,如果是这样,如何决定将执行转移到新线程?
我有来自Tokio docs的以下工作代码,我稍微修改了一下:
// Task
let connection = io::read_exact(socket, buf_read)
.and_then(|(socket, buf_read)| {
println!("Do something with the received data...");
for b in &buf_read {
println!("{}", b);
}
// Write to the socket
let buf_write = vec![19; 30];
io::write_all(socket, buf_write)
})
.then(|res| {
println!("{:?}", res); // Just for testing
//Output: Ok((TcpStream, [19, 19, 19, ...]
println!("Send data...");
let buf_write = vec![18; 10]; // Fill the buffer with some data
//
//How to use the socket contained in res to write the data …Run Code Online (Sandbox Code Playgroud) 在Tokio文档中,有以下代码段:
extern crate tokio;
extern crate futures;
use futures::future::lazy;
tokio::run(lazy(|| {
for i in 0..4 {
tokio::spawn(lazy(move || {
println!("Hello from task {}", i);
Ok(())
}));
}
Ok(())
}));
Run Code Online (Sandbox Code Playgroud)
对此的解释是:
该
lazy函数在第一次对将来进行轮询时运行关闭。在这里使用它来确保tokio::spawn从任务中调用。如果不使用lazy,tokio::spawn则会从任务的上下文外部调用它,从而导致错误。
尽管对Tokio有所了解,但我不确定我是否能准确理解。看来这两个lazy角色的作用略有不同,并且这种解释仅适用于第一个。难道不是在这里lazy(在for循环内)第二次调用将闭包转换为未来吗?