将 socket2 与 hyper 一起使用

Using socket2 with hyper

我正在编写一个 http 服务器,它通过 unix 域套接字与其主机一起工作。服务器是使用 hyper 编写的,我通过 socket2 连接到 UDS。

这是我的代码:

let socket = Socket::new(Domain::UNIX, Type::STREAM, None)?;
let socket_address = SockAddr::unix("unix://tmp/test.sock")?;
socket.bind(&socket_address)?;
socket.listen(128)?;
let server = hyper::server::Server::builder(socket.into()).serve(service);

正确的做法是什么?我收到一条错误消息,提示 无法为类型参数 I

推断类型
error[E0698]: type inside `async fn` body must be known in this context
  --> src/server.rs:65:64
   |
65 |     let server = hyper::server::Server::builder(socket.into()).serve(service);
   |                                                                ^^^^^ cannot infer type for type parameter `I`
   |
note: the type is part of the `async fn` body because of this `await`
  --> src/server.rs:66:13
   |
66 |     let _ = server.await?;
   |             ^^^^^^^^^^^^

Ihyper::server::Server 的通用参数。虽然我知道是什么导致了这个问题:编译器无法确定 socket.into() 被转换成什么,但我不知道如何解决它。

理解有误请指正。我可以得到一些帮助吗?

您需要将套接字转换为tokio::net::UnixListener. Once you have done this, you need an implementation of the Accept trait 等类型。您可以通过以下方式实现该特征:

use hyper::server::accept::Accept;
use tokio::net::UnixListener;

use std::pin::Pin;
use std::task::{Context, Poll};

pub struct UDSAccept {
    inner: UnixListener,
}

impl Accept for UDSAccept {
    type Conn = tokio::net::UnixStream;
    type Error = std::io::Error;

    fn poll_accept(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
        match self.inner.poll_accept(cx) {
            Poll::Pending => Poll::Pending,
            Poll::Ready(Ok((socket, _addr))) => Poll::Ready(Some(Ok(socket))),
            Poll::Ready(Err(err)) => Poll::Ready(Some(Err(err))),
        }
    }
}

以上类型可用作 Server::builder.

的参数

如果 Tokio 类型自带的构造函数没有提供你需要的所有选项,而你仍然希望使用 socket2 来构造它,你可以先将它转换为 std UnixListener 然后调用 Tokio 的 from_std 方法。请注意,执行此操作时必须自己将套接字设置为非阻塞模式!