如何通过LIBC设置TCPSTream的索克特?

发布于 2025-01-21 08:40:25 字数 2303 浏览 3 评论 0原文

我知道tcpStreamstream.set_read_timeout,但我需要在Windows的libc中进行操作,但我的代码不起作用,我相信它是因为我无法理解将毫秒放入_value中的方法: *const c_char。在Rust中,我写了让qtie = [100] .as_ptr();但错误。我也不知道 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);
            }
        }
    }
}

I know TcpStream has stream.set_read_timeout but I need to make it in libc for Windows, but my code don´t works and I believe it is because I can't understand the way to put milliseconds in _value: *const c_char. In Rust I wrote let qtie = [100].as_ptr(); but its wrong. I also don't know how return a c_int in extern "C" fn.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

眼眸里的那抹悲凉 2025-01-28 08:40:25

根据 socket manpage

指定接收或发送超时直到报告
错误。该参数是一个结构时空。

幸运的是,libc板条板定义结构以便您可以做到这一点:


    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 Pointer。

请注意,libc还定义了所需的所有常数,因此您无需自己定义它们。

另外,不要忘记从setSockopt检查返回值。它将返回0以取得成功,而错误为-1。错误代码将在errno中可用,在Rust中,您可以通过 error :: last_os_error()。raw_os_error()

According to the socket manpage:

Specify the receiving or sending timeouts until reporting
an error. The argument is a struct timeval.

Luckily, the libc crate defines that structure so you can do this:


    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,
        );
    };

In order to get the rust reference into a void * pointer, you need to cast it twice: once to a pointer to the type, then to the void pointer.

Note that libc also defines all the constants you need, so you don't need to define them yourself.

Also don't forget to check the return value from setsockopt. It will return 0 for success and -1 for an error. The error code will be available in errno, which in rust you can access via Error::last_os_error().raw_os_error().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文