首页 > 解决方案 > SslStream读取不返回客户端的消息

问题描述

我正在尝试使用 TLS (openssl) 实现客户端-服务器应用程序。我按照 rust doc 中给出的示例作为我的代码结构:示例
服务器代码

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什么也不返回。此外,当服务器服务器写入其消息时,客户端能够接收到该消息。 因此,我使用 SslStream 的方式或配置服务器的方式是否存在问题

标签: ssltcprustopensslsslstream

解决方案


我假设当你说stream.read什么都不返回时,它返回一个零值,表示没有读取任何内容。

Read特征 API 是这样说的:

这个函数不提供任何关于它是否阻塞等待数据的保证,但是如果一个对象需要阻塞读取并且不能,它通常会通过一个 Err 返回值来发出信号。

如果 n 为 0,则它可以指示以下两种情况之一:

  • 此阅读器已到达其“文件末尾”,可能不再能够生成字节。请注意,这并不意味着阅读器将不再能够生成字节。

  • 指定的缓冲区长度为 0 字节。

如果返回值 n 小于缓冲区大小,则不是错误,即使读取器尚未位于流的末尾。例如,这可能是因为现在实际可用的字节较少(例如接近文件结尾)或因为 read() 被信号中断。

因此,您需要反复调用read,直到收到您期望的所有字节,否则会出错。

如果您确切知道要读取多少(就像在本例中所做的那样),您可以调用read_exactwhich 将准确读取填充提供的缓冲区所需的字节数。

如果您想阅读直到分隔符(例如换行符或其他字符),您可以使用 a BufReader,它提供诸如read_untilor之类的方法read_line


推荐阅读