【问题标题】:Reading from TcpStream results in empty buffer从 TcpStream 读取导致空缓冲区
【发布时间】:2018-03-12 01:30:18
【问题描述】:

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

【问题讨论】:

    标签: tcp rust tcpclient


    【解决方案1】:

    由于不同的原因,您尝试的两种方法都不起作用:

    • 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_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()

    虽然这两个代码 sn-ps 是不等价的!请阅读文档以获取更多详细信息。

    【讨论】:

    • 首先感谢您的有用回答。我遇到的问题 - 与 read_to_end 相同。填充缓冲区实际上最多需要 3 秒,因为 python 脚本在几毫秒内运行。由于 rust 是一种快速的语言,我相信我错过了一些东西
    • @xhallix 奇怪。在这种情况下,您必须向您的问题添加更多信息。您的TcpBuilder 不是标准库中的,那么它来自哪里?
    • 来自github.com/rust-lang-nursery/net2-rs。但我对标准 TcpStream 也有同样的问题。 tcpBuilder 实际上给了我std::net::TcpStream btw。如果您愿意,我们可以在 gitter 或其他地方继续此聊天 - 以防止向此线程发送垃圾邮件
    猜你喜欢
    • 1970-01-01
    • 2012-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多