ssl - 如何使用 rustls 库建立 TLS 连接?
问题描述
该文档提供了一个示例 - 不幸的是它无法编译;很多东西都被重命名了,ClientSession
构造函数的接口也发生了变化。我设法将错误修复到它可以编译的地步,但没有修复到它可以工作的地步。
这是我使最小示例起作用的最佳尝试:
extern crate rustls;
use io::Read;
use io::Write;
use rustls::Session;
use std::io;
fn main() {
let mut socket = std::net::TcpStream::connect("www.google.com:443").unwrap();
let mut config = rustls::ClientConfig::new();
config
.root_store
.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
let arc = std::sync::Arc::new(config);
let dns_name = webpki::DNSNameRef::try_from_ascii_str("www.google.com").unwrap();
let mut client = rustls::ClientSession::new(&arc, dns_name);
client.write(b"GET https://www.google.com\r\n\r\n").unwrap();
loop {
if client.wants_read() {
client.read_tls(&mut socket).unwrap();
client.process_new_packets().unwrap();
let mut plaintext = Vec::new();
client.read_to_end(&mut plaintext).unwrap();
io::stdout().write(&plaintext).unwrap();
}
if client.wants_write() {
client.write_tls(&mut socket).unwrap();
}
// For testing purposes only
std::thread::sleep_ms(1000);
}
}
发生的情况是程序开始运行并在 10 秒后中止,并出现错误“已建立的连接已被主机中的软件中止”。
我本来希望它将一些数据打印到标准输出,但事实并非如此。
解决方案
调用了一个结构rustls::Stream
来将会话用作普通流。它记录在docs.rs上。您还可以在他们的 GitHub 存储库中找到示例。
您可以将代码转换为这样使用rustls::Stream
:
extern crate rustls; // 0.17.0
use io::Read;
use io::Write;
use std::io;
fn main() {
let mut socket = std::net::TcpStream::connect("www.google.com:443").unwrap();
let mut config = rustls::ClientConfig::new();
config
.root_store
.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
let arc = std::sync::Arc::new(config);
let dns_name = webpki::DNSNameRef::try_from_ascii_str("www.google.com").unwrap();
let mut client = rustls::ClientSession::new(&arc, dns_name);
let mut stream = rustls::Stream::new(&mut client, &mut socket); // Create stream
// Instead of writing to the client, you write to the stream
stream
.write(b"GET / HTTP/1.1\r\nConnection: close\r\n\r\n")
.unwrap();
let mut plaintext = Vec::new();
stream.read_to_end(&mut plaintext).unwrap();
io::stdout().write_all(&plaintext).unwrap();
}
推荐阅读
- javascript - 在 2 个 div 的碰撞中,使用 Javascript 在其中一个中添加一个类
- r - R:将日期从每天转换为每周并绘制它们
- javascript - 如何在 Firebase 存储参考中使用变量
- c - 初始化一个包含 20 个元素的数组以稍后更新值,但数组的某些元素在 C 中以非零开头?这是为什么?
- python - 删除数据集中字符串的结尾(python)
- javascript - 如何挂载像 codepen 这样的 Vue 3 CLI 项目
- c# - 试图获得骰子卷的随机数
- php - 带有 MySQL 驱动程序的 Laravel 8 原子锁根据 Web 浏览器执行不同的操作
- flutter - 如何在颤振上共享特定页面
- python - 通过插入单个数字来获得最大可能数字的有效算法