Rust 如何使用Tokio从TcpStream读取单个数据包?

Rust 如何使用Tokio从TcpStream读取单个数据包?,rust,rust-tokio,Rust,Rust Tokio,我正在尝试使用tokio接收单个数据包: extern crate tokio; extern crate tokio_io; use tokio::net::{TcpListener}; use tokio::prelude::*; use std::net::SocketAddr; fn main() { let addr = "0.0.0.0:8080".parse::<SocketAddr>().unwrap(); let socket = TcpList

我正在尝试使用tokio接收单个数据包:

extern crate tokio;
extern crate tokio_io;

use tokio::net::{TcpListener};
use tokio::prelude::*;

use std::net::SocketAddr;
fn main() {
    let addr = "0.0.0.0:8080".parse::<SocketAddr>().unwrap();
    let socket = TcpListener::bind(&addr).unwrap();
    println!("Listening on: {}", addr);

    let done = socket
        .incoming()
        .map_err(|e| println!("failed to accept socket; error = {:?}", e))
        .for_each(move |mut socket| {
            let mut bytes = vec![];
            bytes.reserve(1024);
            let processor = socket.read_buf(&mut bytes).into_future()
                .and_then(move |_size| {
                    println!("bytes: {:?}", bytes);
                    Ok(())
                })
                .map_err(|_| ());;
            tokio::spawn(processor)
        });
    tokio::run(done);
}
extern板条箱东京;
外部板条箱东京;
使用tokio::net::{TcpListener};
使用东京::前奏::*;
使用std::net::SocketAddr;
fn main(){
让addr=“0.0.0.0:8080”。解析::()。展开();
让socket=TcpListener::bind(&addr).unwrap();
println!(“监听:{}”,地址);
完成=插座
.incoming()
.map_err(| e | println!(“无法接受套接字;错误={:?}”,e))
.对于每个(移动多个插座){
让mut bytes=vec![];
字节。保留(1024);
让processor=socket.read_buf(&mut bytes).到_future()中
.然后(移动| |大小|{
println!(“字节:{:?}”,字节);
好(())
})
.map|err(| |());;
东京:产卵(处理器)
});
东京:运行(完成);
}

这个代码打印一个空包。如何更改此代码以打印接收到的数据包?

如果您的目标确实是接收一个数据包,我认为您已经成功了

我已经测试了这个程序好几次了,我得到了回复。我正在测试:

nc 127.0.0.1 8080 <<< hello
正如您所看到的,有时我们已经准备好了数据,有时我们没有。我认为在你的测试中,你只是运气不好,在发送任何数据之前才得到TCP响应

我大约90%确信TCP流可以包含空数据包,这就是我们所看到的。(如果有人在这里有更多的知识,请随意编辑答案或评论)


要修复您的程序,您可能需要重新考虑您的目标

读取一个TCP数据包似乎很少有帮助。通常,您希望读取一定数量的字节,并在数据到达时进行处理。我对TCP的理解是字节流,而不是真正的数据包流。数据包只是从一个地方到另一个地方获取字节的一种方式,它们可以是任意长度,而不会破坏兼容性。“一包”是一个相当模糊的概念

下面是一个使用函数读取流的前16个字节的示例:

extern crate tokio;

use tokio::net::TcpListener;
use tokio::prelude::*;

use std::net::SocketAddr;

fn main() {
    let addr = "0.0.0.0:8080".parse::<SocketAddr>().unwrap();
    let socket = TcpListener::bind(&addr).unwrap();
    println!("Listening on: {}", addr);

    let done = socket
        .incoming()
        .map_err(|e| println!("failed to accept socket; error = {:?}", e))
        .for_each(move |mut socket| {
            // this function deals with bytes a bit differently and will just fill the
            // buffer exactly rather than adding onto the end.
            let mut bytes = vec![0; 16];
            let processor = tokio::io::read_exact(socket, bytes)
                .and_then(move |(socket, bytes)| {
                    println!("bytes: {:?}", bytes);
                    Ok(())
                })
                .map_err(|_| ());
            tokio::spawn(processor)
        });
    tokio::run(done);
}
extern板条箱东京;
使用tokio::net::TcpListener;
使用东京::前奏::*;
使用std::net::SocketAddr;
fn main(){
让addr=“0.0.0.0:8080”。解析::()。展开();
让socket=TcpListener::bind(&addr).unwrap();
println!(“监听:{}”,地址);
完成=插座
.incoming()
.map_err(| e | println!(“无法接受套接字;错误={:?}”,e))
.对于每个(移动多个插座){
//此函数处理字节的方式稍有不同,只会填充
//缓冲区完全相同,而不是添加到末尾。
让mut bytes=vec![0;16];
让处理器=tokio::io::读取精确(套接字,字节)
.和|然后(移动|(套接字,字节)|{
println!(“字节:{:?}”,字节);
好(())
})
.map|err(| |());
东京:产卵(处理器)
});
东京:运行(完成);
}

就我自己而言,我几乎找到了答案。非常有用。

struct AsWeGetIt(R);
AsWeGetIt的impl流
哪里
R:AsyncRead,
{
类型项=字节数;
类型错误=std::io::Error;
fn轮询(&mut self)->轮询{
设mut buf=BytesMut::具有_容量(1000);
self.0
.read_buf(&mut buf)
.map(| async | async.map(| | Some(buf)))
}
}
....
让处理器=AsWeGetIt(socket).into_future()
。然后(|(字节,|)|{
println!(“字节:{:?}”,字节);
好(())
}).map|err(| |());
但为了更好地理解如何在没有单独结构的情况下。。。
地图为什么要用,用什么?

嗯。。。很奇怪。我玩代码。如果我删除
字节,则保留(1024)然后定期收到完整消息。很可能我们需要添加一些条件来检查消息sizeI是否有90%的答案,我们将很快发布它。我认为我之前的评论是错误的,这就是我删除它的原因。请不要在你的问题中给出答案。欢迎您回答下面的问题,甚至接受这个答案。这是更好的,因为它允许更多的答案和那些答案由社区投票。read_exact解决了另一个问题。所以我们总是等待确切的尺寸。下面是如何准确地读取在阻塞模式下读取时发生的事情。据我所知,这是空的消息不能(在任何情况下,他们不会进入用户空间)
extern crate tokio;

use tokio::net::TcpListener;
use tokio::prelude::*;

use std::net::SocketAddr;

fn main() {
    let addr = "0.0.0.0:8080".parse::<SocketAddr>().unwrap();
    let socket = TcpListener::bind(&addr).unwrap();
    println!("Listening on: {}", addr);

    let done = socket
        .incoming()
        .map_err(|e| println!("failed to accept socket; error = {:?}", e))
        .for_each(move |mut socket| {
            // this function deals with bytes a bit differently and will just fill the
            // buffer exactly rather than adding onto the end.
            let mut bytes = vec![0; 16];
            let processor = tokio::io::read_exact(socket, bytes)
                .and_then(move |(socket, bytes)| {
                    println!("bytes: {:?}", bytes);
                    Ok(())
                })
                .map_err(|_| ());
            tokio::spawn(processor)
        });
    tokio::run(done);
}
struct AsWeGetIt<R>(R);

impl<R> Stream for AsWeGetIt<R>
    where
        R: AsyncRead,
{
    type Item = BytesMut;
    type Error = std::io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let mut buf = BytesMut::with_capacity(1000);

        self.0
            .read_buf(&mut buf)
            .map(|async| async.map(|_| Some(buf)))
    }
}
....
let processor = AsWeGetIt(socket).into_future()
.and_then(|(bytes,_)|  {
    println!("bytes: {:?}", bytes);
    Ok(())
}).map_err(|_| ());