简体   繁体   English

C ++ read() - 从套接字到ofstream

[英]C++ read()-ing from a socket to an ofstream

Is there a C/C++ way to read data from a socket using read() and having the receiving buffer be a file (ofstream) or a similar self-extending object (vector eg)? 是否有一种C / C ++方法使用read()从套接字读取数据并使接收缓冲区是文件(ofstream)或类似的自扩展对象(例如)?

EDIT: The question arose while I contemplated how to read a stream socket that may receive the contents of a, say 10000+ byte file. 编辑:当我考虑如何读取可能接收10000+字节文件的内容的流套接字时出现了问题。 I just never did like putting 20000 or 50000 bytes (large enough for now) on the stack as a buffer where the file could be stored temporarily till I could stick in into a file. 我从来没有像把20000或50000字节(现在足够大)放在堆栈上作为缓冲区,文件可以临时存储,直到我可以插入文件。 Why not just stream it directly into the file to star with. 为什么不直接将其直接流入文件中以加注星标。

Much like you can get at the char* inside a std:string, I thought of something like 就像你可以在std:string里面的char *那样,我想到了类似的东西

read( int fd, outFile.front(), std::npos );  // npos = INT_MAX

or something like that. 或类似的东西。

end edit 结束编辑

Thanks. 谢谢。

This is simplistic, and off the top of my fingers, but I think something along these lines would work out: 这是简单的,并且在我的手指之上,但我认为沿着这些方向的东西会成功:

template <unsigned BUF_SIZE>
struct Buffer {
    char buf_[BUF_SIZE];
    int len_;
    Buffer () : buf_(), len_(0) {}
    int read (int fd) {
        int r = read(fd, buf_ + len_, BUF_SIZE - len_);
        if (r > 0) len_ += r;
        return r;
    }
    int capacity () const { return BUF_SIZE - len_; }
}

template <unsigned BUF_SIZE>
struct BufferStream {
    typedef std::unique_ptr< Buffer<BUF_SIZE> > BufferPtr;
    std::vector<BufferPtr> stream_;
    BufferStream () : stream_(1, BufferPtr(new Buffer<BUF_SIZE>)) {}
    int read (int fd) {
        if ((*stream_.rbegin())->capacity() == 0)
            stream_.push_back(BufferPtr(new Buffer<BUF_SIZE>));
        return (*stream_.rbegin())->read(fd);
    }
};

In a comment, you mentioned you wanted to avoid creating a big char buffer. 在评论中,您提到您想避免创建一个大的char缓冲区。 When using the read system call, it is generally more efficient to perform a few large reads rather than many small ones. 当使用read系统调用时,执行一些大读取而不是许多小读取通常更有效。 So most implementations will opt for large input buffers to gain that efficiency. 因此,大多数实现将选择大输入缓冲区来获得该效率。 You could implement something like: 你可以实现类似的东西:

std::vector<char> input;
char in;
int r;
while ((r = read(fd, &in, 1)) == 1) input.push_back(in);

But that would involve a system call and at least one byte copied for every byte of input. 但这将涉及系统调用,并且每个输入字节至少复制一个字节。 In contrast, the code I put forth avoids extra data copies. 相反,我提出的代码避免了额外的数据副本。

I don't really expect the code I put out to be the solution you would adopt. 我真的不希望我提出的代码是你要采用的解决方案。 I just wanted to provide you with an illustration of how to create a self-extending object that was fairly space and time efficient. 我只想向您提供如何创建一个空间和时间效率相当高的自扩展对象的说明。 Depending on your purposes, you may want to extend it, or write your own. 根据您的目的,您可能希望扩展它,或编写自己的。 Off the top of my head, some improvements may be: 在我的头顶,一些改进可能是:

  • use std::list instead, to avoid vector resizing 使用std::list代替,以避免向量调整大小
  • allow API a parameter to specify how many bytes to read 允许API一个参数来指定要读取的字节数
  • use readv to always allow at least BUF_SIZE bytes (or more than BUF_SIZE bytes) to be read at a time 使用readv始终允许至少BUF_SIZE字节(或多于BUF_SIZE字节)在同一时间内读

看一下boost::asio中的流支持。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM