问题描述
我正在编写一个 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?;
| ^^^^^^^^^^^^
I
是 hyper::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
方法。请注意,执行此操作时必须自己将套接字设置为非阻塞模式!