Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
190 views
in Technique[技术] by (71.8m points)

ssl - SslStream<TcpStream> read does not return client's message

I am trying to implement a client-server application using TLS (openssl). I followed the example given in rust doc for my code's structure: example
Server Code

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");
}

Client Code

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");
}

The Server code and the client code both compile without issues, albeit with some warnings. The client is able to connect to the server. But when the client writes its message From Client to the stream, the stream.read called in handle_client() returns nothing. Furthermore, when the server writes its message From Server, the client is able to receive that. Hence, is there an issue with the way I use SslStream or on the way I configured my server?

question from:https://stackoverflow.com/questions/65878583/sslstreamtcpstream-read-does-not-return-clients-message

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I presume when you say stream.read returns nothing, that it returns a zero value indicating that nothing was read.

The Read trait API says this:

This function does not provide any guarantees about whether it blocks waiting for data, but if an object needs to block for a read and cannot, it will typically signal this via an Err return value.

If n is 0, then it can indicate one of two scenarios:

  • This reader has reached its "end of file" and will likely no longer be able to produce bytes. Note that this does not mean that the reader will always no longer be able to produce bytes.

  • The buffer specified was 0 bytes in length.

It is not an error if the returned value n is smaller than the buffer size, even when the reader is not at the end of the stream yet. This may happen for example because fewer bytes are actually available right now (e. g. being close to end-of-file) or because read() was interrupted by a signal.

So, you need to repeatedly call read until you receive all the bytes you expect, or you get an error.

If you know exactly how much you want to read (as you do in this case) you can call read_exact which will read exactly the number of bytes needed to fill the supplied buffer.

If you want to read up until a delimeter (such as a newline or other character) you can use a BufReader, which provides methods such as read_until or read_line.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...