如何通过 libc 设置 TcpStream 的 sockopt?
How do I setsockopt of a TcpStream via libc?
我知道 TcpStream
有 stream.set_read_timeout
但我需要在 libc
中为 Windows 添加它,但我的代码不起作用,我相信这是因为我无法理解将毫秒放入 _value: *const c_char
的方法。在 Rust 中我写了 let qtie = [100].as_ptr();
但它错了。我也不知道 return 如何在 extern "C" fn
.
中出现 c_int
use std::net::{TcpListener, TcpStream};
use std::io::{Read, Write};
use std::thread;
use std::time::Duration;
use libc::c_int;
use libc::c_char;
pub unsafe extern "C" fn setsockopt(
_socket: c_int,
_nivel: c_int,
_nombre: c_int,
_value: *const c_char,
_option_len: c_int
) -> c_int {return 0;}
fn al_cliente(mut stream: TcpStream) {
const SOL_SOCKET:i32 = 1; // También 0xffff
const SO_RCVTIMEO:i32 = 20;
const SO_SNDTIMEO:i32 = 21;
const tam_buff:usize = 10;
let mut data = [0 as u8; tam_buff];
loop {
println!("{:?}", stream);
let buska = format!("{:?}", stream);
let arrsk:Vec<&str> = buska.split(" ").collect();
let socket = arrsk[7].parse::<i32>().unwrap();
//let socket = 0;
println!("{}", socket);
let qtie = [100].as_ptr();
// Ejemplo: int nTimeout = 5000; // 5 seconds
// setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&nTimeout, sizeof(int));
unsafe { setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, qtie, 10); }
//stream.set_read_timeout(Some(Duration::from_secs(10)));
let ver = stream.read(&mut data).unwrap();
stream.write(&data[0..tam_buff]).unwrap();
let atexto = String::from_utf8_lossy(&data);
println!("{:?}", atexto);
}
}
fn main() {
let listener = TcpListener::bind("0.0.0.0:3333").unwrap();
println!("Server listening on port 3333");
for stream in listener.incoming() {
match stream {
Ok(stream) => {
println!("Conectado: {}", stream.peer_addr().unwrap());
let _hilo = thread::spawn(move || {
al_cliente(stream);
});
}
Err(e) => {
println!("Error: {}", e);
}
}
}
}
根据 socket manpage:
Specify the receiving or sending timeouts until reporting
an error. The argument is a struct timeval.
幸运的是,libc crate defines that structure 所以你可以这样做:
let sock_timeout = libc::timeval {
tv_sec: 10,
tv_usec: 0,
};
let result = unsafe {
libc::setsockopt(
socket,
libc::SOL_SOCKET,
libc::SO_RCVTIMEO,
&sock_timeout as *const libc::timeval as *const libc::c_void,
std::mem::size_of::<libc::timeval>() as u32,
);
};
为了将 Rust 引用转换为 void *
指针,您需要将其转换两次:一次转换为指向该类型的指针,然后转换为 void 指针。
注意libc
也定义了你需要的所有常量,所以你不需要自己定义它们。
另外不要忘记检查 setsockopt
中的 return 值。它将 return 0 表示成功,-1 表示错误。错误代码将在 errno
中可用,在 Rust 中,您可以通过 Error::last_os_error().raw_os_error()
.
访问
我知道 TcpStream
有 stream.set_read_timeout
但我需要在 libc
中为 Windows 添加它,但我的代码不起作用,我相信这是因为我无法理解将毫秒放入 _value: *const c_char
的方法。在 Rust 中我写了 let qtie = [100].as_ptr();
但它错了。我也不知道 return 如何在 extern "C" fn
.
c_int
use std::net::{TcpListener, TcpStream};
use std::io::{Read, Write};
use std::thread;
use std::time::Duration;
use libc::c_int;
use libc::c_char;
pub unsafe extern "C" fn setsockopt(
_socket: c_int,
_nivel: c_int,
_nombre: c_int,
_value: *const c_char,
_option_len: c_int
) -> c_int {return 0;}
fn al_cliente(mut stream: TcpStream) {
const SOL_SOCKET:i32 = 1; // También 0xffff
const SO_RCVTIMEO:i32 = 20;
const SO_SNDTIMEO:i32 = 21;
const tam_buff:usize = 10;
let mut data = [0 as u8; tam_buff];
loop {
println!("{:?}", stream);
let buska = format!("{:?}", stream);
let arrsk:Vec<&str> = buska.split(" ").collect();
let socket = arrsk[7].parse::<i32>().unwrap();
//let socket = 0;
println!("{}", socket);
let qtie = [100].as_ptr();
// Ejemplo: int nTimeout = 5000; // 5 seconds
// setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&nTimeout, sizeof(int));
unsafe { setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, qtie, 10); }
//stream.set_read_timeout(Some(Duration::from_secs(10)));
let ver = stream.read(&mut data).unwrap();
stream.write(&data[0..tam_buff]).unwrap();
let atexto = String::from_utf8_lossy(&data);
println!("{:?}", atexto);
}
}
fn main() {
let listener = TcpListener::bind("0.0.0.0:3333").unwrap();
println!("Server listening on port 3333");
for stream in listener.incoming() {
match stream {
Ok(stream) => {
println!("Conectado: {}", stream.peer_addr().unwrap());
let _hilo = thread::spawn(move || {
al_cliente(stream);
});
}
Err(e) => {
println!("Error: {}", e);
}
}
}
}
根据 socket manpage:
Specify the receiving or sending timeouts until reporting an error. The argument is a struct timeval.
幸运的是,libc crate defines that structure 所以你可以这样做:
let sock_timeout = libc::timeval {
tv_sec: 10,
tv_usec: 0,
};
let result = unsafe {
libc::setsockopt(
socket,
libc::SOL_SOCKET,
libc::SO_RCVTIMEO,
&sock_timeout as *const libc::timeval as *const libc::c_void,
std::mem::size_of::<libc::timeval>() as u32,
);
};
为了将 Rust 引用转换为 void *
指针,您需要将其转换两次:一次转换为指向该类型的指针,然后转换为 void 指针。
注意libc
也定义了你需要的所有常量,所以你不需要自己定义它们。
另外不要忘记检查 setsockopt
中的 return 值。它将 return 0 表示成功,-1 表示错误。错误代码将在 errno
中可用,在 Rust 中,您可以通过 Error::last_os_error().raw_os_error()
.