1

我正在尝试使用 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);
}

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

4

2 回答 2

1

对于我自己,我几乎找到了答案。非常有帮助类似的问题

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

但是为了更好地理解如何在没有单独结构的情况下做...以及为什么以及使用什么地图?

于 2018-06-13T06:57:03.097 回答
0

如果你的目标真的是收到一包,我想你已经成功了!

我已经对该程序进行了几次测试,并得到了响应。我正在测试:

nc 127.0.0.1 8080 <<< hello

运行几次后,我得到以下输出:

Listening on: 0.0.0.0:8080
bytes: [104, 101, 108, 108, 111, 10]
bytes: []
bytes: [104, 101, 108, 108, 111, 10]
bytes: []
bytes: [104, 101, 108, 108, 111, 10]
bytes: []
bytes: [104, 101, 108, 108, 111, 10]
bytes: [104, 101, 108, 108, 111, 10]

如您所见,有时我们已经准备好数据,有时我们没有。我认为在您的测试中,您只是运气不佳,并且在发送任何数据之前才获得 TCP 响应?

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


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

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

这是一个使用tokio::io::read_exact函数读取流的前 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);
}
于 2018-06-12T22:40:25.303 回答