2016-11-07 13 views
1

Ich habe die Dokumentation für std::net und mio lesen, und ich habe einige Methoden wie set_nodelay und set_keepalive gefunden, aber ich habe keinen Weg, um andere Socket-Optionen wie SO_REUSEPORT und SO_REUSEADDR auf einem bestimmten Sockel gefunden. Wie kann ich das machen?Wie setze ich die Socket-Option SO_REUSEPORT in Rust?

+0

Ich weiß, mein Programm unter Linux läuft. – huron

Antwort

3

Da SO_REUSEPORT isn't cross-platform, müssen Sie in Plattform-spezifischen Code eintauchen. In diesem Fall können Sie die RAW-Datei-Descriptor aus der Steckdose und dann verwenden Funktionen, Typen und Werte aus der libc Kiste die Optionen festlegen, die Sie wollen:

extern crate libc; 

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

fn main() { 
    let listener = TcpListener::bind("0.0.0.0:8888").expect("Unable to bind"); 

    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 { 
      let err: Result<(), _> = Err(io::Error::last_os_error()); 
      err.expect("setsockopt failed"); 
     } 
    } 

    println!("Hello, world!"); 
} 

ich keine Garantie, dass dies die richtige ist Ort, um diese Option zu setzen, oder dass ich etwas in dem unsicheren Block nicht vermasselt habe, aber es kompiliert und läuft auf macOS 10.12.

Eine noch bessere Lösung kann die nix crate zu überprüfen, die für die meisten * nichts-spezifischen Code schöneren Wrapper bietet: nur

extern crate nix; 

use std::net::TcpListener; 
use std::os::unix::io::AsRawFd; 
use nix::sys::socket; 
use nix::sys::socket::sockopt::ReusePort; 

fn main() { 
    let listener = TcpListener::bind("0.0.0.0:8888").expect("Unable to bind"); 
    socket::setsockopt(listener.as_raw_fd(), ReusePort, &true).expect("setsockopt failed"); 

    println!("Hello, world!"); 
}