问题描述
我正在尝试使用 TLS (openssl) 实现客户端-服务器应用程序。我按照 rust doc 中给出的示例来了解我的代码结构:example
服务器代码
fn handle_client(mut stream: SslStream<Tcpstream>){
println!("Passed in handling method");
let mut data = vec![];
let length = stream.read(&mut data).unwrap();
println!("read successfully; size read:{}",length);
stream.write(b"From server").unwrap();
stream.flush().unwrap();
println!("{}",String::from_utf8_lossy(&data));
}
fn main() {
//remember: certificate should always be signed
let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
acceptor.set_private_key_file("src/keyfile/key.pem",SslFiletype::PEM).unwrap();
acceptor.set_certificate_file("src/keyfile/certs.pem",SslFiletype::PEM).unwrap();
acceptor.check_private_key().unwrap();
let acceptor = Arc::new(acceptor.build());
let listener = TcpListener::bind("127.0.0.1:9000").unwrap();
for stream in listener.incoming(){
match stream{
Ok(stream)=>{
println!("a receiver is connected");
let acceptor = acceptor.clone();
//thread::spawn(move || {
let stream = acceptor.accept(stream).unwrap();
handle_client(stream);
//});
}
Err(_e)=>{println!{"connection Failed"}}
}
}
println!("Server");
}
客户端代码
fn main() {
let mut connector = SslConnector::builder(SslMethod::tls()).unwrap();
connector.set_verify(SslVerifyMode::NONE); //Deactivated verification due to authentication error
connector.set_ca_file("src/keyfile/certs.pem");
let connector = connector.build();
let stream = Tcpstream::connect("127.0.0.1:9000").unwrap();
let mut stream = connector.connect("127.0.0.1",stream).unwrap();
stream.write(b"From Client").unwrap();
stream.flush().unwrap();
println!("client sent its message");
let mut res = vec![];
stream.read_to_end(&mut res).unwrap();
println!("{}",String::from_utf8_lossy(&res));
// stream.write_all(b"client").unwrap();
println!("Client");
}
服务器代码和客户端代码都编译没有问题,尽管有一些警告。客户端能够连接到服务器。但是当客户端将其消息 From Client 写入流时,handle_client() 中调用的 stream.read 不返回任何内容。此外,当服务器写入其消息 From Server 时,客户端能够接收到该消息。 因此,我使用 SslStream 的方式或配置服务器的方式是否存在问题?
解决方法
我认为当你说 stream.read
什么都不返回时,它返回一个零值,表明没有读取任何内容。
Read
trait API 是这样说的:
该函数不提供是否阻塞的任何保证 等待数据,但如果一个对象需要阻塞读取和 不能,它通常会通过 Err 返回值发出信号。
如果 n 为 0,那么它可以表示以下两种情况之一:
-
此阅读器已到达其“文件结尾”,可能不会再出现 能够产生字节。请注意,这并不意味着读者 将永远无法再产生字节。
-
指定的缓冲区长度为 0 字节。
返回值n小于缓冲区不是错误 大小,即使阅读器还没有到达流的末尾。这 例如,可能会发生,因为实际上可用的字节数较少 现在(例如接近文件尾)或因为 read() 是 被信号中断。
因此,您需要反复调用 read
直到收到您期望的所有字节,否则会出现错误。
如果您确切地知道要读取多少(如本例中所做的那样),您可以调用 read_exact
,它将准确读取填充提供的缓冲区所需的字节数。
如果您想一直读到分隔符(例如换行符或其他字符),您可以使用 BufReader
,它提供诸如 read_until
或 read_line
之类的方法。>