利用标准库容器封装char,实现自动增长的缓冲区
缓冲区的自动增长的实现原理
web服务器之缓冲区的自动增长的实现原理
socket通信中的分散读和集中写



分散读示例
在Linux下,readv系统调用可以实现分散读(scattered read),即从一个文件描述符中读取数据到多个缓冲区中。下面是一个使用readv的C++示例,演示了如何从文件中分散读取数据:
#include <iostream>  
#include <fcntl.h>  
#include <unistd.h>  
#include <vector>  
#include <sys/uio.h>  
  
int main() {  
    // 打开文件  
    int fd = open("example.txt", O_RDONLY);     // 文件内容:hello,world
    if (fd == -1) {  
        std::cerr << "Failed to open file" << std::endl;  
        return 1;  
    }  
  
    // 定义要读取的缓冲区  
    /* Structure for scatter/gather I/O.  */
    /*
        struct iovec
        {
            void *iov_base;	// Pointer to data.
            size_t iov_len;	// Length of data.
        };
    */
    std::vector<struct iovec> buffers;  
    buffers.emplace_back();  
    buffers.back().iov_base = (char*)malloc(5);  
    buffers.back().iov_len = 5;  
  
    buffers.emplace_back();  
    buffers.back().iov_base = (char*)malloc(1);  
    buffers.back().iov_len = 1;  
    buffers.emplace_back();  
    buffers.back().iov_base = (char*)malloc(5);  
    buffers.back().iov_len = 5;  
  
    // 读取数据  
    ssize_t bytesRead = readv(fd, buffers.data(), buffers.size());  
    if (bytesRead == -1) {  
        std::cerr << "Failed to read data" << std::endl;  
        close(fd);  
        return 1;  
    }
    std::cout << "bytesRead = " << bytesRead << std::endl;
    // 输出读取的数据  
    for (const auto& buffer : buffers) {  
        std::cout.write((char*)buffer.iov_base, buffer.iov_len) << std::endl;  
    }  
  
    // 释放缓冲区并关闭文件  
    for (auto& buffer : buffers) {  
        free((char*)buffer.iov_base);  
    }  
    close(fd);  
  
    return 0;  
}
/*
输出:
bytesRead = 11
hello
,
world
*/
这段代码主要演示了如何使用 readv 函数从文件中进行分散读取,也就是从一个文件中读取数据到多个缓冲区中。下面是对这段代码的详细解释:
- 
头文件引入
<iostream>: 用于C++标准输入输出。<fcntl.h>和<unistd.h>: 这两个头文件包含了文件操作(如open和close)和低级I/O操作(如readv)的函数声明。<vector>: C++标准库中的动态数组。<sys/uio.h>: 包含iovec结构的定义,这个结构用于readv和writev函数的分散/聚集I/O。
 - 
主函数
- 
打开文件:使用
open函数打开名为 "example.txt" 的文件,并设置其为只读模式。如果文件打开失败,程序将输出错误消息并返回1。 - 
定义要读取的缓冲区:使用
std::vector来存储多个iovec结构。每个iovec结构代表一个缓冲区,其中iov_base是指向数据的指针,iov_len是数据的长度。- 第一个缓冲区大小为5,用于存储 "hello" 中的前5个字符。
 - 第二个缓冲区大小为1,用于存储逗号 ","。
 - 第三个缓冲区大小为5,用于存储 "world" 中的5个字符。
 
 - 
读取数据:使用
readv函数从文件中读取数据。这个函数将从文件描述符fd指向的文件中读取数据,并将数据分散到buffers向量中的多个缓冲区中。readv返回实际读取的字节数。如果读取失败,程序将输出错误消息,关闭文件并返回1。 - 
输出读取的数据:遍历
buffers向量,并使用std::cout.write函数将每个缓冲区中的数据输出到标准输出。 - 
释放缓冲区并关闭文件:在输出数据后,使用
free函数释放每个缓冲区分配的内存,并使用close函数关闭文件。 
 - 
 - 
输出
- 输出实际读取的字节数,即11。
 - 接着输出从文件中读取的内容,即 "hello\n,\nworld\n"。每个缓冲区的内容后面都有一个换行符,这是因为 
std::cout.write函数不会自动添加换行符,所以在每次写入后都需要手动添加。 
 
    Do not communicate by sharing memory; instead, share memory by communicating.

                
            
        
浙公网安备 33010602011771号