从TcpStream读取会导致空缓冲区

时间:2017-09-30 07:53:50

标签: tcp rust tcpclient

我想从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中实现这一目标?

1 个答案:

答案 0 :(得分:4)

您尝试的两种方法由于不同原因而无法运作:

  • read():"不保证是否阻止等待数据"。一般来说,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_exaxt(&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()

这两个代码片段虽然不相同!请阅读文档以获取更多详细信息。