- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试从 UnixStream
(在此代码中称为 socket
)读取一些未知大小的数据。数据由 6 个字节的 header 组成,最后两个字节表示消息的其余部分应该有多长。
.into_buf()
我调用的方法来自 Tokio 的 bytes
crate 中的 IntoBuf
特性。
let mut header = [0u8; 6];
let response1 = self.socket.read(&mut header);
let mut cursor = header.into_buf();
let evt_code = cursor.get_u16_le();
let controller = cursor.get_u16_le();
let param_size = cursor.get_u16_le() as usize;
let mut param = vec![0u8; param_size];
let response2 = self.socket.read(&mut param);
let mut cursor = param.into_buf();
我遇到的问题是 response2
始终是 Err
E_WOULDBLOCK,因为我的 UnixStream
连接到非阻塞套接字。似乎第一次调用 read()
是按预期读取 6 个字节,但随后只是丢弃了流中的其余内容。
我该如何解决这个问题/如何让 read()
将额外的数据留在流中?
看起来最简单的解决方案是让我的初始缓冲区变大,然后一次读取所有内容,但问题是我可以接收的最大可能消息超过 64KB。为每次读取分配或重新归零 64KB 缓冲区似乎很浪费,尤其是因为大多数消息都比这小得多。
最佳答案
我通过使用原始文件描述符而不是 UnixStream
并使用 MSG_PEEK
调用 recv()
来解决这个问题。
let mut header = [0u8; 6];
// need MSG_PEEK otherwise recv() clears the socket and we get EAGAIN when
// we try to read the socket again; this is the main reason for using a raw
// fd instead of a UnixStream
if unsafe { libc::recv(self.fd, header.as_mut_ptr() as *mut c_void, 6, libc::MSG_PEEK) } < 0 {
return Err(io::Error::last_os_error().into());
}
let mut cursor = header.into_buf();
let evt_code = cursor.get_u16_le();
let controller = cursor.get_u16_le();
let param_size = cursor.get_u16_le() as usize;
// since calling recv() with MSG_PEEK doesn't consume the header, we need to make
// this buffer 6 bytes bigger, but that's fine
let mut param = vec![0u8; param_size + 6];
if unsafe { libc::recv(self.fd, param.as_mut_ptr() as *mut c_void, param.len(), 0) } < 0 {
return Err(io::Error::last_os_error().into());
}
let mut cursor = param.into_buf();
关于linux - 如何从连接到套接字的 UnixStream 一次读取一点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58140920/
我有一个问题的这个小示例版本: #[test] fn streams() { use std::io::prelude::*; use std::net::Shutdown;
我正在尝试从 UnixStream(在此代码中称为 socket)读取一些未知大小的数据。数据由 6 个字节的 header 组成,最后两个字节表示消息的其余部分应该有多长。 .into_buf()我
tokio::run_async + futures 0.3 + tokio::net::UnixStream panic 。 设置 [package] name = "prac" version =
我是一名优秀的程序员,十分优秀!