Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets 如何将数据从套接字读取到现有缓冲区的偏移量中?_Sockets_Tcp_Rust - Fatal编程技术网

Sockets 如何将数据从套接字读取到现有缓冲区的偏移量中?

Sockets 如何将数据从套接字读取到现有缓冲区的偏移量中?,sockets,tcp,rust,Sockets,Tcp,Rust,根据我对TCP的理解,如果我将X字节发送到套接字,几乎可以保证它会到达那里,尽管有效负载可能会分割并分为两部分到达(因此,如果我等待一个25字节的数据包,我可能会得到20个字节,然后在下一次读取时额外得到5个字节)。我从未见过这种情况发生,但我希望在这种情况发生时被报道 在过去,我通常设计套接字读取来解释这一点——将传入字节读入缓冲区,然后不断检查缓冲区的大小。如果整个数据包有足够的数据,请处理该数据包,从缓冲区前端删除字节,然后继续 我现在正试图在Rust中编写一个类似的系统,为TCP套接字使

根据我对TCP的理解,如果我将X字节发送到套接字,几乎可以保证它会到达那里,尽管有效负载可能会分割并分为两部分到达(因此,如果我等待一个25字节的数据包,我可能会得到20个字节,然后在下一次读取时额外得到5个字节)。我从未见过这种情况发生,但我希望在这种情况发生时被报道

在过去,我通常设计套接字读取来解释这一点——将传入字节读入缓冲区,然后不断检查缓冲区的大小。如果整个数据包有足够的数据,请处理该数据包,从缓冲区前端删除字节,然后继续

我现在正试图在Rust中编写一个类似的系统,为TCP套接字使用
mio
。我的缓冲区只是一个数组:
[u8;最大缓冲区大小]
下面是我的套接字读取代码:

loop {
    // Read until there are no more incoming bytes
    match socket.read(&mut buffer) {
        Ok(0) => {
            // Socket is closed, Client has disconnected!
            // (perform disconnection here)
            break;
        },
        Ok(read_bytes) => {
            println!("Read {} bytes from client", read_bytes);
        },
        Err(e) => {
            if e.kind() == io::ErrorKind::WouldBlock {
                // Socket is not ready anymore, stop reading
                break;
            }
        }
    }
}
这不支持读取任何分割数据,因为
read
函数只是覆盖缓冲区开头的数据,而不是将后续调用追加到结尾。在C和C++中,有一个偏移参数可以提供给等效调用,以允许这种行为,但是我无法理解如何用<代码> MIO < /代码>来完成。我找不到任何偏移参数这一事实使我相信,在我理解
read
函数的过程中,我遗漏了一些重要的东西

我如何编程套接字读取来解释这一点

我找不到任何偏移参数这一事实让我相信我遗漏了一些重要的东西

是的,但它与套接字无关。锈有片,这是一种更普遍的解决办法。要获取缓冲区的子集,请从所需偏移量开始获取一个切片。数据将被读入与原始缓冲区偏移量相同的片的开头:

socket.read(&mut buffer[offset..])
读取完毕后,可以取一个切片,以防止在缓冲区中查看无用的尾随数据:

let my_data = &buffer[..total_read_bytes];
// do something with my_data
一个完整的例子:

use std::io::prelude::*;

const MAX_LEN: usize = 64;

fn main() {
    let dummy_data = b"this is a very long bit of data";
    let mut dummy_data = &dummy_data[..];

    let mut buffer = [0; MAX_LEN];

    let mut offset = 0;
    offset += dummy_data
        .by_ref()
        .take(4)
        .read(&mut buffer[offset..])
        .unwrap();
    offset += dummy_data
        .by_ref()
        .take(4)
        .read(&mut buffer[offset..])
        .unwrap();

    let final_data = &buffer[..offset];

    let s = std::str::from_utf8(final_data);
    println!("{:?}", s);
    assert_eq!(s, Ok("this is "));
}

您可能还对以下方面感兴趣:

此函数根据需要读取尽可能多的字节以完全填充指定的缓冲区
buf

我找不到任何偏移参数这一事实让我相信我遗漏了一些重要的东西

是的,但它与套接字无关。锈有片,这是一种更普遍的解决办法。要获取缓冲区的子集,请从所需偏移量开始获取一个切片。数据将被读入与原始缓冲区偏移量相同的片的开头:

socket.read(&mut buffer[offset..])
读取完毕后,可以取一个切片,以防止在缓冲区中查看无用的尾随数据:

let my_data = &buffer[..total_read_bytes];
// do something with my_data
一个完整的例子:

use std::io::prelude::*;

const MAX_LEN: usize = 64;

fn main() {
    let dummy_data = b"this is a very long bit of data";
    let mut dummy_data = &dummy_data[..];

    let mut buffer = [0; MAX_LEN];

    let mut offset = 0;
    offset += dummy_data
        .by_ref()
        .take(4)
        .read(&mut buffer[offset..])
        .unwrap();
    offset += dummy_data
        .by_ref()
        .take(4)
        .read(&mut buffer[offset..])
        .unwrap();

    let final_data = &buffer[..offset];

    let s = std::str::from_utf8(final_data);
    println!("{:?}", s);
    assert_eq!(s, Ok("this is "));
}

您可能还对以下方面感兴趣:

此函数根据需要读取尽可能多的字节以完全填充指定的缓冲区
buf