如何在 Rust 中设置套接字选项 SO_REUSEPORT?

Posted

技术标签:

【中文标题】如何在 Rust 中设置套接字选项 SO_REUSEPORT?【英文标题】:How to set the socket option SO_REUSEPORT in Rust? 【发布时间】:2017-03-21 00:05:01 【问题描述】:

我已经阅读了 std::net 和 mio 的文档,并且找到了一些方法,例如 set_nodelayset_keepalive,但我还没有找到设置其他套接字选项的方法,例如 SO_REUSEPORTSO_REUSEADDR 在给定的套接字上。我该怎么做?

【问题讨论】:

【参考方案1】:

因为SO_REUSEPORT isn't cross-platform,您需要深入了解特定于平台的代码。在这种情况下,您可以从套接字获取原始文件描述符,然后使用 libc crate 中的函数、类型和值来设置您想要的选项:

extern crate libc; // 0.2.43

use std::io, mem, net::TcpListener, os::unix::io::AsRawFd;

fn main() -> Result<(), io::Error> 
    let listener = TcpListener::bind("0.0.0.0:8888")?;

    unsafe 
        let optval: libc::c_int = 1;
        let ret = libc::setsockopt(
            listener.as_raw_fd(),
            libc::SOL_SOCKET,
            libc::SO_REUSEPORT,
            &optval as *const _ as *const libc::c_void,
            mem::size_of_val(&optval) as libc::socklen_t,
        );
        if ret != 0 
            return Err(io::Error::last_os_error());
        
    

    Ok(())

我不保证这是设置此选项的正确位置,或者我没有搞砸 unsafe 块中的某些内容,但它确实可以在 macOS 10.12 上编译和运行。

更好的解决方案可能是查看nix crate,它为大多数 *nix 特定代码提供了更好的包装器:

extern crate nix; // 0.11.0

use nix::sys::socket::self, sockopt::ReusePort;
use std::error::Error, net::TcpListener, os::unix::io::AsRawFd;

fn main() -> Result<(), Box<Error>> 
    let listener = TcpListener::bind("0.0.0.0:8888")?;
    socket::setsockopt(listener.as_raw_fd(), ReusePort, &true)?;

    Ok(())

更好的解决方案可能是查看net2 crate,它提供了专门针对网络相关代码的更高级别的方法:

extern crate net2; // 0.2.33

use net2::unix::UnixTcpBuilderExt, TcpBuilder;

fn main() -> Result<(), std::io::Error> 
    let listener = TcpBuilder::new_v4()?
        .reuse_address(true)?
        .reuse_port(true)?
        .bind("0.0.0.0:8888")?
        .listen(42)?;

    Ok(())

【讨论】:

以上是关于如何在 Rust 中设置套接字选项 SO_REUSEPORT?的主要内容,如果未能解决你的问题,请参考以下文章

如何在Java代码中设置TCP_CORK选项

通过 SO_RCVTIMEO 套接字选项在 Ruby 中设置套接字超时

如何在 azure 中设置安全的 Web 套接字

如何在 boost asio 中设置阻塞套接字的超时时间?

如何在c中设置UDP套接字中的源端口?

VC++ socket编程中设置socket选项的ioctlsocketsetsockopt和WSAIoctl函数的使用(附源码)