gpt4 book ai didi

sockets - 使用 TcpStream 强制非阻塞读取

转载 作者:可可西里 更新时间:2023-11-01 02:30:40 29 4
gpt4 key购买 nike

我有一个线程,它维护一个套接字列表,我想遍历该列表,看看是否有任何要读取的内容,如果有 - 对其进行操作,如果没有 - 移动到下一个。问题是,一旦我遇到第一个节点,所有执行都会停止,直到读取完成。

我正在使用 std::io::Read::read(&mut self, buf: &mut [u8]) -> Result<usize>

来自doc

This function does not provide any guarantees about whether it blocks waiting for data, but if an object needs to block for a read but cannot it will typically signal this via an Err return value.

深挖源码,TcpStream Read的实现是

impl Read for TcpStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
}

调用

pub fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
let fd = self.fd();
let dolock = || self.lock_nonblocking();
let doread = |nb| unsafe {
let flags = if nb {c::MSG_DONTWAIT} else {0};
libc::recv(fd,
buf.as_mut_ptr() as *mut libc::c_void,
buf.len() as wrlen,
flags) as libc::c_int
};
read(fd, self.read_deadline, dolock, doread)
}

最后,调用 read<T, L, R>(fd: sock_t, deadline: u64, mut lock: L, mut read: R)

在检索到数据或发生错误之前,我可以看到非阻塞读取循环。

有没有办法强制使用 TcpStream 进行非阻塞读取? ?

最佳答案

更新的答案

应该注意的是,从 Rust 1.9.0 开始,std::net::TcpStream增加了功能:

fn set_nonblocking(&self, nonblocking: bool) -> Result<()>

原始答案

用TcpStream无法准确获取,又不想拉入单独的lib用于IO操作,所以决定在使用前将文件描述符设置为Non-blocking,并执行系统调用读取/写。绝对不是最安全的解决方案,但比实现新的 IO 库工作更少,即使 MIO看起来很棒。

extern "system" {
fn read(fd: c_int, buffer: *mut c_void, count: size_t) -> ssize_t;
}

pub fn new(user: User, stream: TcpStream) -> Socket {

// First we need to setup the socket as Non-blocking on POSIX
let fd = stream.as_raw_fd();
unsafe {
let ret_value = libc::fcntl(fd,
libc::consts::os::posix01::F_SETFL,
libc::consts::os::extra::O_NONBLOCK);

// Ensure we didnt get an error code
if ret_value < 0 {
panic!("Unable to set fd as non-blocking")
}
}

Socket {
user: user,
stream: stream
}
}

pub fn read(&mut self) {
let count = 512 as size_t;
let mut buffer = [0u8; 512];
let fd = self.stream.as_raw_fd();

let mut num_read = 0 as ssize_t;
unsafe {
let buf_ptr = buffer.as_mut_ptr();
let void_buf_ptr: *mut c_void = mem::transmute(buf_ptr);
num_read = read(fd, void_buf_ptr, count);
if num_read > 0 {
println!("Read: {}", num_read);
}

println!("test");
}
}

关于sockets - 使用 TcpStream 强制非阻塞读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28503514/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com