gpt4 book ai didi

rust - UdpSocket.recv_from 失败并显示 "end of file"但我可以在 Wireshark 中看到传入的包

转载 作者:行者123 更新时间:2023-11-29 08:14:56 25 4
gpt4 key购买 nike

Editor's note: This code example is from a version of Rust prior to 1.0 and is not valid Rust 1.0 code. The concepts discussed in the question are still valid.

我正在尝试使用 Rust 进行 torrent 抓取。我可以在 Wireshark 中看到传入的包,但我的 recv_from 调用总是返回 Error("End of file")。这是我的程序:

use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::io::net::udp::UdpSocket;
use std::rand;

use std::io::MemWriter;

fn main() {
let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 35000 };
let mut socket = match UdpSocket::bind(addr) {
Ok(s) => s,
Err(e) => panic!("couldn't bind socket: {}", e),
};

let mut buf: Vec<u8> = Vec::with_capacity(1000);

let transaction_id: u32 = rand::random();
let mut req_data = MemWriter::with_capacity(16);
req_data.write_be_u64(0x41727101980).unwrap(); // connection_id, identifies the protocol.
req_data.write_be_u32(0).unwrap(); // action: connect
req_data.write_be_u32(transaction_id).unwrap();

println!("{}", socket.send_to(req_data.get_ref(), ("31.172.63.252", 80)));

match socket.recv_from(buf.as_mut_slice()) {
Ok((amt, src)) => {
println!("Got {} bytes from {}.", amt, src);
},
Err(err) => println!("Can't recv_from: {}", err)
}
}

输出总是:

➜  udp-bug git:(master) ✗ cargo run
Compiling udp-bug v0.0.1 (file:///home/omer/rust/udp-bug)
Running `target/udp-bug`
Ok(())
Can't recv_from: end of file

但是,我可以在 Wireshark 中看到预期的响应:

20235   3512.148636000  31.172.63.252   192.168.1.4 QUIC    60  CID: 0, Seq: 0

这个包有一个 16 字节的负载,这正是我所期望的。出了什么问题?

最佳答案

Editor's note: This code example is from a version of Rust prior to 1.0 and is not valid Rust 1.0 code. The concepts discussed in the answer are still valid.

我认为您的问题是您将 Vec::with_capacity() 用作可变切片。 Vec::with_capacity() 仅创建具有指定容量(自然)的向量,但其长度为零。因此,从向量中取出的切片的长度也将为零:

let v = Vec::with_capacity(128);
println!("{}", v.as_mut_slice().len()); // prints 0

切片无法增长,因此 recv_from() 没有可写入的空间,因此失败并出现错误。

您基本上有两个选择。第一个是使用不安全的 set_len() 方法:

let mut buf: Vec<u8> = Vec::with_capacity(1000);
unsafe { buf.set_len(1000); }

这样缓冲区将具有正确的长度,但其内容可能只是垃圾。然而,这对于这个用例来说并不是很重要,只要您只访问正确数量的字节(使用 recv_from() 返回的信息)即可。

不过,还有更好的方法。您可以使用堆栈分配的固定大小数组:

let mut buf = [0u8, ..1000];

// ...

match socket.recv_from(buf.as_mut_slice()) {
// ...
}

req_data 也一样:您可以使用静态大小的数组和 BufWriter :

let transaction_id: u32 = rand::random();
let mut req_data_buf = [0u8, ..16];
let mut req_data = BufWriter::new(req_data_buf);
req_data.write_be_u64(0x41727101980).unwrap(); // connection_id, identifies the protocol.
req_data.write_be_u32(0).unwrap(); // action: connect
req_data.write_be_u32(transaction_id).unwrap();

println!("{}", socket.send_to(req_data_buf, ("31.172.63.252", 80)));

不过这只适用于固定大小的缓冲区。如果您不知道缓冲区的大小,您仍然需要一个 Vec

关于rust - UdpSocket.recv_from 失败并显示 "end of file"但我可以在 Wireshark 中看到传入的包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26778657/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com