SslStream<TcpStream> 读取不返回客户端的消息

问题描述

我正在尝试使用 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_untilread_line 之类的方法。>