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?
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(())
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With