How to set the socket option SO_REUSEPORT in Rust?

ぃ、小莉子 提交于 2019-12-10 18:58:46

问题


I've read the documentation for std::net and mio, and I've found some methods like set_nodelay and set_keepalive, but I haven't found a way to set other socket options like SO_REUSEPORT and SO_REUSEADDR on a given socket. How can I do this?


回答1:


Because SO_REUSEPORT isn't cross-platform, you will need to dip into platform-specific code. In this case, you can get the raw file descriptor from the socket and then use functions, types, and values from the libc crate to set the options you want:

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(())
}

I make no guarantee that this is the right place to set this option, or that I haven't screwed up something in the unsafe block, but it does compile and run on macOS 10.12.

A better solution may be to check out the nix crate, which provides nicer wrappers for most *nix-specific code:

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(())
}

An even better solution may be to check out the net2 crate, which provides higher-level methods aimed specifically at networking-related code:

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(())
}


来源:https://stackoverflow.com/questions/40468685/how-to-set-the-socket-option-so-reuseport-in-rust

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!