将 socket2 与 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() 被强制转换为什么,但我不知道如何解决它。

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

解决方法

需要将socket转换成tokio::net::UnixListener等类型。完成此操作后,您需要实现 Accept 特征。您可以通过以下方式实现该特征:

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 {{1} } 然后调用 Tokio 的 from_std 方法。请注意,执行此操作时必须自己将套接字设置为非阻塞模式!