#unix #tokio #clap #tcp-socket #systemd #tcp-connection #socket-activation

tokio-listener

通过以下方式接受连接增加灵活性:Unix 套接字、套接字激活、inetd 模式到基于 Tokio 的项目

11 个不稳定版本 (3 个破坏性更新)

0.4.3 2024 年 7 月 9 日
0.4.2 2024 年 5 月 15 日
0.3.2 2024 年 3 月 16 日
0.3.1 2024 年 2 月 7 日
0.1.0 2023 年 7 月 30 日

#611网络编程

Download history 30/week @ 2024-04-29 17/week @ 2024-05-06 373/week @ 2024-05-13 35/week @ 2024-05-20 30/week @ 2024-05-27 28/week @ 2024-06-03 56/week @ 2024-06-10 16/week @ 2024-06-17 23/week @ 2024-06-24 70/week @ 2024-07-01 104/week @ 2024-07-08 51/week @ 2024-07-15 49/week @ 2024-07-22 138/week @ 2024-07-29 57/week @ 2024-08-05 45/week @ 2024-08-12

每月 305 次下载
3 crates 中使用

MIT/Apache

110KB
2K SLoC

原因

使用 Hyper 或 Axum Rust 框架创建的 Web 服务项目通常允许用户指定要绑定以监听传入连接的 TCP 端口和主机。虽然这是一个稳健的默认选择,但有时需要更多的灵活性,尤其是在 Linux 上。

tokio-listener 通过提供特殊的抽象类型 ListenerAddressListener 而不是典型的 SocketAddrTcpListener,以轻松方式为项目增加这种灵活性。

特性

监听模式

  • 监听 UNIX 套接字而不是 TCP 套接字。它由地址以 ./ 开头触发。
  • 在 Linux 上监听抽象命名空间的 UNIX 套接字。它由地址以 @ 开头触发。
  • 从父进程继承的已打开套接字接受连接(例如 systemd)。这由特殊的地址 sd-listen 触发。您还可以请求特定的命名套接字或所有套接字。
  • Inetd 模式 - stdin/stdout 也可以用于服务一个连接。

其他

  • 可移植性 - 不支持的平台不会编译复杂特性
  • clap 集成 - 可以将自定义地址添加为 Clap 字段(由于 FromStr 实现)。其他选项也可以通过 clap::flatten() 包括,这还带来了简短的文档到 CLI 帮助消息。或者,可以使用 ListenerAddressPositionalListenerAddressLFlag 辅助类型将整个主地址和附加选项集引入。
  • serde 集成 - 自定义地址类型在 Serde 中表现得像字符串。其他选项也可以序列化或反序列化。
  • 对于 UNIX 路径套接字,它支持根据用户请求解除链接、更改所有者权限和更改权限。
  • axum 0.7 集成。
  • 多监听器 - 同时绑定多个端口的简单方式。结合systemd支持,还可以通过特殊的 sd-listen:* 地址来触发多监听。默认未启用。
  • 细粒度编译时功能开关。在不启用功能的情况下,它应该基本上减少到对普通 TcpListener 的薄包装。

示例

  • clap_axum - 最简单、最直接的示例。使用Clap作为CLI框架和Axum作为Web框架。该示例有两个版本:一个适用于Axum 0.6,另一个适用于Axum 0.7。
  • argh_hyper - 展示如何使用非clap CLI解析器。还直接使用 hyper 而不是Axum。
  • serde_echo - 展示监听配置也可以使用例如toml文件来指定。它不是一个Web服务,而是一个echo服务器。

有关API参考和一些其他示例,请参阅 crate文档

限制

  • 不支持SEQPACKET或DGRAM套接字。
  • 可能比直接使用TcpListener慢,因为每个发送或接收都需要通过包装器进行。如果您在编译时禁用UNIX和inetd模式,这种减慢应该会消失。
  • 不支持为UNIX套接字指定非UTF8兼容的路径。

示例会话

给定这一系列调用

target/debug/examples/clap_axum07 127.0.0.1:8080   $'Hello from usual mode\n'
target/debug/examples/clap_axum07 ./path_socket    $'Hello from UNIX socket path mode\n'
target/debug/examples/clap_axum07 @abstract_socket $'Hello from UNIX socket abstract mode\n'
systemd-socket-activate          -l 8081 target/debug/examples/clap_axum07   sd-listen   $'Hello from pre-listened socket\n'
systemd-socket-activate --inetd -al 8082 target/debug/examples/clap_axum07   inetd       $'Hello from inetd mode\n'
systemd-socket-activate -l 8083 -l 8084 --fdname=foo:bar -- target/debug/examples/clap_axum07   sd-listen:bar   $'Hello from a named pre-listened socket\n'
systemd-socket-activate -l 8085 -l 8086 -- target/debug/examples/clap_axum07   sd-listen:*   $'Hello from any of the two pre-listened sockets\n'

以及这个 Caddyfile

{
    admin off
}
:4000

handle_path /tcp/* {
    reverse_proxy 127.0.0.1:8080
}
handle_path /unix/* {
    reverse_proxy unix/./path_socket
}
handle_path /abstract/* {
    reverse_proxy unix/@abstract_socket
}
handle_path /sdlisten/* {
    reverse_proxy 127.0.0.1:8081
}
handle_path /inetd/* {
    reverse_proxy 127.0.0.1:8082
}

您可以看到,实际上可以通过多种方式访问相同的服务

$ curl http://127.0.0.1:4000/tcp/
Hello from usual mode
$ curl http://127.0.0.1:4000/unix/
Hello from UNIX socket path mode
$ curl http://127.0.0.1:4000/abstract/
Hello from UNIX socket abstract mode
$ curl http://127.0.0.1:4000/sdlisten/
Hello from a pre-listened socket
$ curl http://127.0.0.1:4000/inetd/
Hello from inetd 

$ curl --unix ./path_socket http://q/
Hello from UNIX socket path mode
$ curl --abstract-unix abstract_socket http://q/
Hello from UNIX socket abstract mode

示例的帮助信息

Demo application for tokio-listener

Usage: clap_axum [OPTIONS] <LISTEN_ADDRESS> <TEXT_TO_SERVE>

Arguments:
  <LISTEN_ADDRESS>
          Socket address to listen for incoming connections.
          
          Various types of addresses are supported:
          
          * TCP socket address and port, like 127.0.0.1:8080 or [::]:80
          
          * UNIX socket path like /tmp/mysock or Linux abstract address like @abstract
          
          * Special keyword "inetd" for serving one connection from stdin/stdout
          
          * Special keyword "sd-listen" to accept connections from file descriptor 3 (e.g. systemd socket activation).
            You can also specify a named descriptor after a colon or * to use all passed sockets (if this feature is enabled).

  <TEXT_TO_SERVE>
          Line of text to return as a body of incoming requests

Options:
      --unix-listen-unlink
          remove UNIX socket prior to binding to it

      --unix-listen-chmod <UNIX_LISTEN_CHMOD>
          change filesystem mode of the newly bound UNIX socket to `owner`, `group` or `everybody`

      --unix-listen-uid <UNIX_LISTEN_UID>
          change owner user of the newly bound UNIX socket to this numeric uid

      --unix-listen-gid <UNIX_LISTEN_GID>
          change owner group of the newly bound UNIX socket to this numeric uid

      --sd-accept-ignore-environment
          ignore environment variables like LISTEN_PID or LISTEN_FDS and unconditionally use file descritor `3` as a socket in sd-listen or sd-listen-unix modes

      --tcp-keepalive <TCP_KEEPALIVE>
          set SO_KEEPALIVE settings for each accepted TCP connection.

          Value is a colon-separated triplet of time_ms:count:interval_ms, each of which is optional.

      --tcp-reuse-port
          Try to set SO_REUSEPORT, so that multiple processes can accept connections from the same port in a round-robin fashion

      --recv-buffer-size <RECV_BUFFER_SIZE>
          Set socket's SO_RCVBUF value

      --send-buffer-size <SEND_BUFFER_SIZE>
          Set socket's SO_SNDBUF value

      --tcp-only-v6
          Set socket's IPV6_V6ONLY to true, to avoid receiving IPv4 connections on IPv6 socket

      --tcp-listen-backlog <TCP_LISTEN_BACKLOG>
          Maximum number of pending unaccepted connections

  -h, --help
          Print help (see a summary with '-h')

所有这些都可以通过一个 #[clap(flatten)] addr: tokio_listener::ListenerAddressPositional 来实现。

依赖关系

~3–14MB
~159K SLoC