从 TcpStream 读取导致空缓冲区 [英] Reading from TcpStream results in empty buffer

查看:86
本文介绍了从 TcpStream 读取导致空缓冲区的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从 TCP 流中读取数据,但结果是一个空的 Vec:

I want to read data from a TCP stream but it results in an empty 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 时,缓冲区已满,但这需要太长时间.

When I use stream.read_to_end the buffer is filled but this takes way too long.

在 Python 中我可以做类似的事情

In Python I can do something like

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 中实现这一点?

How can I achieve this in Rust?

推荐答案

您尝试的两种方法均无效,原因不同:

The two methods you tried don't work for different reasons:

  • 阅读():不提供任何关于它是否阻塞等待数据的保证".一般来说,read() 从用户的角度来看是不可靠的,只能用作更高级别函数的构建块,例如 read_to_end().

  • read(): "does not provide any guarantees about whether it blocks waiting for data". In general, read() is unreliable from a users perspective and should only be used as a building block for higher level functions, like read_to_end().

但也许更重要的是,您的代码中有一个错误:您通过 with_capacity() 创建向量,该向量在内部保留内存,但不会更改向量的长度.它仍然是空的!当你现在像 &buf 一样切片时,你将一个空切片传递给 read(),因此 read() 无法读取任何实际数据.为了解决这个问题,你的向量的元素需要被初始化: let mut buf = vec![0;1024] 或类似的东西.

But maybe more importantly, you have a bug in your code: you create your vector via with_capacity() which reserves memory internally, but doesn't change the length of the vector. It is still empty! When you now slice it like &buf, you pass an empty slice to read(), thus read() cannot read any actual data. To fix that, the elements of your vector need to be initialized: let mut buf = vec![0; 1024] or something like that.

read_to_end():重复调用read(),直到遇到EOF.这在大多数 TCP 流情况下实际上没有意义.

read_to_end(): calls read() repeatedly until EOF is encountered. This doesn't really make sense in most TCP stream situations.

那你应该用什么来代替?在您的 Python 代码中,您将特定数量的字节读入缓冲区.你也可以在 Rust 中做到这一点:<代码>read_exact().它是这样工作的:

So what should you use instead? In your Python code you read a specific number of bytes into a buffer. You can do that in Rust, too: read_exact(). It works like this:

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);

如果你想多次使用流,你可能想使用 by_ref() 在调用 take() 之前.

If you want to use the stream multiple times, you probably want to use by_ref() before calling take().

不过,这两个代码片段并不等效!请阅读文档以获取更多详细信息.

The two code snippets are not equivalent though! Please read the documentation for more details.

这篇关于从 TcpStream 读取导致空缓冲区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆