6

我正在尝试在 Hyper Web 服务器中创建一个计数器,用于计算它收到的请求数。我正在使用 aArc<Mutex<u64>>来保持计数。但是,我无法找出正确的组合move.clone()满足闭包的类型。这是一些可以编译的代码,但会在每个请求上重置计数器:

extern crate hyper;

use hyper::rt::Future;
use hyper::service::service_fn_ok;
use hyper::{Body, Response, Server};
use std::sync::{Arc, Mutex};

fn main() {
    let addr = "0.0.0.0:3000".parse().unwrap();
    // FIXME want to create the counter here, not below
    let server = Server::bind(&addr)
        .serve(|| {
            service_fn_ok(|_req| {
                let counter = Arc::new(Mutex::new(0));
                use_counter(counter)
            })
        })
        .map_err(|e| eprintln!("Error: {}", e));
    hyper::rt::run(server)
}

fn use_counter(counter: Arc<Mutex<u64>>) -> Response<Body> {
    let mut data = counter.lock().unwrap();
    *data += 1;
    Response::new(Body::from(format!("Counter: {}\n", data)))
}
4

1 回答 1

10

事实证明我已经很接近了,看看其他一些例子帮助我意识到了这个问题。由于这里有两层闭包,我需要将其counter移入外部闭包,克隆它,然后将该克隆移入内部闭包并再次克隆。以机智:

extern crate hyper; // 0.12.10

use hyper::rt::Future;
use hyper::service::service_fn_ok;
use hyper::{Body, Response, Server};
use std::sync::{Arc, Mutex};

fn main() {
    let addr = "0.0.0.0:3000".parse().unwrap();
    let counter = Arc::new(Mutex::new(0));
    let server = Server::bind(&addr)
        .serve(move || {
            let counter = counter.clone();
            service_fn_ok(move |_req| use_counter(counter.clone()))
        })
        .map_err(|e| eprintln!("Error: {}", e));
    hyper::rt::run(server)
}

fn use_counter(counter: Arc<Mutex<u64>>) -> Response<Body> {
    let mut data = counter.lock().unwrap();
    *data += 1;
    Response::new(Body::from(format!("Counter: {}\n", data)))
}

2020 年 2 月更新这是使用 hyper 0.13 的版本:

use hyper::{Body, Response, Server, Request};
use std::sync::{Arc, Mutex};
use hyper::service::{make_service_fn, service_fn};
use std::convert::Infallible;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let addr = "0.0.0.0:3000".parse()?;
    let counter = Arc::new(Mutex::new(0));

    let make_service = make_service_fn(move |_conn| {
        let counter = counter.clone();
        async move {
            Ok::<_, Infallible>(service_fn(move |_req: Request<Body>| {
                let counter = counter.clone();
                async move {
                    Ok::<_, Infallible>(use_counter(counter))
                }
            }))
        }
    });

    Server::bind(&addr).serve(make_service).await?;
    Ok(())
}

fn use_counter(counter: Arc<Mutex<u64>>) -> Response<Body> {
    let mut data = counter.lock().unwrap();
    *data += 1;
    Response::new(Body::from(format!("Counter: {}\n", data)))
}
于 2018-10-24T16:39:08.717 回答