Linux 如何从连接到套接字的UnixStream中一次读取一点?

Linux 如何从连接到套接字的UnixStream中一次读取一点?,linux,sockets,unix,rust,Linux,Sockets,Unix,Rust,我试图从UnixStream(在本代码中称为socket)读取一些大小未知的数据。数据由6个字节的头组成,最后两个字节指示消息的剩余部分应该有多长 我调用的方法是从Tokio的bytes板条箱中的IntoBuf特性调用的 let mut header=[0u8;6]; let response1=self.socket.read(&mut头); 让mut cursor=header.into_buf(); 让evt_code=cursor.get_16_le(); 让controller=cur

我试图从
UnixStream
(在本代码中称为
socket
)读取一些大小未知的数据。数据由6个字节的头组成,最后两个字节指示消息的剩余部分应该有多长

我调用的方法是从Tokio的
bytes
板条箱中的
IntoBuf
特性调用的

let mut header=[0u8;6];
let response1=self.socket.read(&mut头);
让mut cursor=header.into_buf();
让evt_code=cursor.get_16_le();
让controller=cursor.get_16_le();
让param_size=cursor.get_16_le()作为usize;
让mut param=vec![0u8;参数大小];
让response2=self.socket.read(&mut param);
让mut cursor=param.into_buf();
我遇到的问题是,
response2
始终是一个
Err
E\u WOULDBLOCK,因为我的
UnixStream
连接到一个非阻塞套接字。对
read()
的第一个调用似乎是按预期读取6个字节,但随后只是丢弃流中的其余内容

如何解决这个问题/如何使
read()
在流中保留额外的数据


看起来最简单的解决方案是将初始缓冲区变大,然后立即读取所有内容,但问题是,我可能收到的最大消息有64KB多一点。为每次读取分配或重新调零一个64KB的缓冲区似乎非常浪费,特别是因为大多数消息都比这个小得多。

我通过使用原始文件描述符而不是
UnixStream
来解决这个问题,并使用
MSG_PEEK
调用
recv()

let mut header=[0u8;6];
//需要MSG_PEEK,否则recv()将清除套接字,我们将在
//我们再次尝试读取套接字;这是使用原材料的主要原因
//fd而不是UnixStream
如果不安全{libc::recv(self.fd,header.as_mut_ptr()as*mut c_void,6,libc::MSG_PEEK)}<0{
返回Err(io::Error::last_os_Error().into());
}
让mut cursor=header.into_buf();
让evt_code=cursor.get_16_le();
让controller=cursor.get_16_le();
让param_size=cursor.get_16_le()作为usize;
//由于使用MSG_PEEK调用recv()不会占用头,因此我们需要
//这个缓冲区大6个字节,但没关系
让mut param=vec![0u8;参数大小+6];
如果不安全{libc::recv(self.fd,param.as_mut_ptr()as*mut c_void,param.len(),0)}<0{
返回Err(io::Error::last_os_Error().into());
}
让mut cursor=param.into_buf();

我通过使用原始文件描述符而不是
UnixStream
来解决这个问题,并使用
MSG_PEEK
调用
recv()

let mut header=[0u8;6];
//需要MSG_PEEK,否则recv()将清除套接字,我们将在
//我们再次尝试读取套接字;这是使用原材料的主要原因
//fd而不是UnixStream
如果不安全{libc::recv(self.fd,header.as_mut_ptr()as*mut c_void,6,libc::MSG_PEEK)}<0{
返回Err(io::Error::last_os_Error().into());
}
让mut cursor=header.into_buf();
让evt_code=cursor.get_16_le();
让controller=cursor.get_16_le();
让param_size=cursor.get_16_le()作为usize;
//由于使用MSG_PEEK调用recv()不会占用头,因此我们需要
//这个缓冲区大6个字节,但没关系
让mut param=vec![0u8;参数大小+6];
如果不安全{libc::recv(self.fd,param.as_mut_ptr()as*mut c_void,param.len(),0)}<0{
返回Err(io::Error::last_os_Error().into());
}
让mut cursor=param.into_buf();

此套接字未连接到网络或文件,我正在使用它与内核API交互。因此,我不知道在这里使用
BufReader
是否有任何意义(我也不知道如果我使用
BufReader
,我将如何读写)如果你不想使用非阻塞模式,为什么你要使用非阻塞模式?@user207421也许我误解了非阻塞模式的确切功能。。。我想如果我使用阻塞模式,那么当我尝试在没有输入的情况下读取套接字时,程序将暂停(这不是期望的行为)@user207421将套接字更改为阻塞模式没有帮助。此套接字未连接到网络或文件,我正在使用它与内核API交互。因此,我不知道在这里使用
BufReader
是否有任何意义(我也不知道如果我使用
BufReader
,我将如何读写)如果你不想使用非阻塞模式,为什么你要使用非阻塞模式?@user207421也许我误解了非阻塞模式的确切功能。。。我想如果我使用阻塞模式,那么当我尝试在没有输入的情况下读取套接字时,程序将暂停(这不是期望的行为)@user207421将套接字更改为阻塞模式没有帮助。