从 TcpStream 读取结果为空缓冲区
Reading from TcpStream results in empty buffer
我想从 TCP 流中读取数据,但结果为空 Vec
:
extern crate net2;
use net2::TcpBuilder;
use std::io::Read;
use std::io::Write;
use std::io::BufReader;
let tcp = TcpBuilder::new_v4().unwrap();
let mut stream = tcp.connect("127.0.0.1:3306").unwrap();
let mut buf = Vec::with_capacity(1024);
stream.read(&mut buf);
println!("{:?}", buf); // prints []
当我使用 stream.read_to_end
时,缓冲区已满,但这需要很长时间。
在 Python 我可以做类似
的事情
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 3306
BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
#s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()
print "received data:", data
我如何在 Rust 中实现这一点?
由于不同的原因,您尝试的两种方法均无效:
read()
: "does not provide any guarantees about whether it blocks waiting for data"。一般来说,read()
从用户的角度来看是不可靠的,只能用作更高级别功能的构建块,如 read_to_end()
.
但也许更重要的是,您的代码中有一个错误:您通过 with_capacity()
创建向量,它在内部保留内存,但不会更改向量的长度。它仍然是空的!当你现在像 &buf
那样切片时,你将一个空切片传递给 read()
,因此 read()
无法读取任何实际数据。要解决这个问题,需要初始化向量的元素:let mut buf = vec![0; 1024]
或类似的东西。
read_to_end()
:重复调用read()
直到遇到EOF。这在大多数 TCP 流情况下实际上没有意义。
那么你应该改用什么?在您的 Python 代码中,您将特定数量的字节读入缓冲区。你也可以在 Rust 中做到这一点:read_exact()
。它是这样工作的:
const BUFFER_SIZE: usize = 1024;
let mut stream = ...;
let mut buf = [0; BUFFER_SIZE];
stream.read_exact(&mut buf);
println!("{:?}", buf);
您也可以使用 take()
。这样你就可以使用 read_to_end()
:
const BUFFER_SIZE: usize = 1024;
let mut stream = ...;
let mut buf = Vec::with_capacity(BUFFER_SIZE);
stream.take(BUFFER_SIZE).read_to_end(&mut buf);
println!("{:?}", buf);
如果你想多次使用流,你可能想在调用 take()
.
之前使用 by_ref()
虽然这两个代码片段并不等同!请阅读文档以获取更多详细信息。
我想从 TCP 流中读取数据,但结果为空 Vec
:
extern crate net2;
use net2::TcpBuilder;
use std::io::Read;
use std::io::Write;
use std::io::BufReader;
let tcp = TcpBuilder::new_v4().unwrap();
let mut stream = tcp.connect("127.0.0.1:3306").unwrap();
let mut buf = Vec::with_capacity(1024);
stream.read(&mut buf);
println!("{:?}", buf); // prints []
当我使用 stream.read_to_end
时,缓冲区已满,但这需要很长时间。
在 Python 我可以做类似
的事情import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 3306
BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
#s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()
print "received data:", data
我如何在 Rust 中实现这一点?
由于不同的原因,您尝试的两种方法均无效:
read()
: "does not provide any guarantees about whether it blocks waiting for data"。一般来说,read()
从用户的角度来看是不可靠的,只能用作更高级别功能的构建块,如read_to_end()
.但也许更重要的是,您的代码中有一个错误:您通过
with_capacity()
创建向量,它在内部保留内存,但不会更改向量的长度。它仍然是空的!当你现在像&buf
那样切片时,你将一个空切片传递给read()
,因此read()
无法读取任何实际数据。要解决这个问题,需要初始化向量的元素:let mut buf = vec![0; 1024]
或类似的东西。read_to_end()
:重复调用read()
直到遇到EOF。这在大多数 TCP 流情况下实际上没有意义。
那么你应该改用什么?在您的 Python 代码中,您将特定数量的字节读入缓冲区。你也可以在 Rust 中做到这一点:read_exact()
。它是这样工作的:
const BUFFER_SIZE: usize = 1024;
let mut stream = ...;
let mut buf = [0; BUFFER_SIZE];
stream.read_exact(&mut buf);
println!("{:?}", buf);
您也可以使用 take()
。这样你就可以使用 read_to_end()
:
const BUFFER_SIZE: usize = 1024;
let mut stream = ...;
let mut buf = Vec::with_capacity(BUFFER_SIZE);
stream.take(BUFFER_SIZE).read_to_end(&mut buf);
println!("{:?}", buf);
如果你想多次使用流,你可能想在调用 take()
.
by_ref()
虽然这两个代码片段并不等同!请阅读文档以获取更多详细信息。