Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.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
C++ 处理套接字描述符,如文件描述符(fstream)?C++/Linux_C++_Linux_Sockets_Stream - Fatal编程技术网

C++ 处理套接字描述符,如文件描述符(fstream)?C++/Linux

C++ 处理套接字描述符,如文件描述符(fstream)?C++/Linux,c++,linux,sockets,stream,C++,Linux,Sockets,Stream,我偶然发现我可以在套接字描述符上使用读写。我是否可以(ab)使用fstream机制将数据输出到套接字描述符中?标准文件流不支持使用文件描述符。然而,I/O流类使得创建自己的抽象变得相当容易,从而可以创建自己的字符源或字符目的地。magic类是std::streambuf,其职责是缓冲字符并在适当的时间读取或写入字符。Nicolai Josuttis的文章详细描述了如何做到这一点(多年前我就以此为基础为Nico撰稿)。使用套接字进行读写的流缓冲区的简单实现如下所示: #include <al

我偶然发现我可以在套接字描述符上使用读写。我是否可以(ab)使用fstream机制将数据输出到套接字描述符中?

标准文件流不支持使用文件描述符。然而,I/O流类使得创建自己的抽象变得相当容易,从而可以创建自己的字符源或字符目的地。magic类是std::streambuf,其职责是缓冲字符并在适当的时间读取或写入字符。Nicolai Josuttis的文章详细描述了如何做到这一点(多年前我就以此为基础为Nico撰稿)。使用套接字进行读写的流缓冲区的简单实现如下所示:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <streambuf>
#include <cstddef>
#include <unistd.h>

class fdbuf
    : public std::streambuf
{
private:
    enum { bufsize = 1024 };
    char outbuf_[bufsize];
    char inbuf_[bufsize + 16 - sizeof(int)];
    int  fd_;
public:
    typedef std::streambuf::traits_type traits_type;

    fdbuf(int fd);
    ~fdbuf();
    void open(int fd);
    void close();

protected:
    int overflow(int c);
    int underflow();
    int sync();
};

fdbuf::fdbuf(int fd)
  : fd_(-1) {
    this->open(fd);
}

fdbuf::~fdbuf() {
    this->close();
}

void fdbuf::open(int fd) {
    this->close();
    this->fd_ = fd;
    this->setg(this->inbuf_, this->inbuf_, this->inbuf_);
    this->setp(this->outbuf_, this->outbuf_ + bufsize - 1);
}

void fdbuf::close() {
    if (!(this->fd_ < 0)) {
        this->sync();
        ::close(this->fd_);
    }
}

int fdbuf::overflow(int c) {
    if (!traits_type::eq_int_type(c, traits_type::eof())) {
        *this->pptr() = traits_type::to_char_type(c);
        this->pbump(1);
    }
    return this->sync() == -1
        ? traits_type::eof()
        : traits_type::not_eof(c);
}

int fdbuf::sync() {
    if (this->pbase() != this->pptr()) {
        std::streamsize size(this->pptr() - this->pbase());
        std::streamsize done(::write(this->fd_, this->outbuf_, size));
        // The code below assumes that it is success if the stream made
        // some progress. Depending on the needs it may be more
        // reasonable to consider it a success only if it managed to
        // write the entire buffer and, e.g., loop a couple of times
        // to try achieving this success.
        if (0 < done) {
            std::copy(this->pbase() + done, this->pptr(), this->pbase());
            this->setp(this->pbase(), this->epptr());
            this->pbump(size - done);
        }
    }
    return this->pptr() != this->epptr()? 0: -1;
}

int fdbuf::underflow()
{
    if (this->gptr() == this->egptr()) {
        std::streamsize pback(std::min(this->gptr() - this->eback(),
                                       std::ptrdiff_t(16 - sizeof(int))));
        std::copy(this->egptr() - pback, this->egptr(), this->eback());
        int done(::read(this->fd_, this->eback() + pback, bufsize));
        this->setg(this->eback(),
                   this->eback() + pback,
                   this->eback() + pback + std::max(0, done));
    }
    return this->gptr() == this->egptr()
        ? traits_type::eof()
        : traits_type::to_int_type(*this->gptr());
}

int main()
{
    fdbuf        inbuf(0);
    std::istream in(&inbuf);
    fdbuf        outbuf(1);
    std::ostream out(&outbuf);

    std::copy(std::istreambuf_iterator<char>(in),
              std::istreambuf_iterator<char>(),
              std::ostreambuf_iterator<char>(out));
}
#包括
#包括
#包括
#包括
#包括
#包括
类fdbuf
:public std::streambuf
{
私人:
枚举{bufsize=1024};
煤焦突出度[bufsize];
char inbuf_[bufsize+16-sizeof(int)];
int fd_;
公众:
typedef std::streambuf::traits_type traits_type;
fdbuf(int-fd);
~fdbuf();
无效开放(int fd);
无效关闭();
受保护的:
int溢出(INTC);
int下溢();
int sync();
};
fdbuf::fdbuf(int-fd)
:fd_u1;(-1){
此->打开(fd);
}
fdbuf::~fdbuf(){
此->关闭();
}
void fdbuf::open(int fd){
此->关闭();
这->fd\ufd=fd;
此->设置(此->输入,此->输入,此->输入);
此->设置(此->突发,此->突发+bufsize-1);
}
void fdbuf::close(){
如果(!(此->fd_u0){
此->同步();
::关闭(此->fd_);
}
}
intfdbuf::溢出(intc){
如果(!traits_type::eq_int_type(c,traits_type::eof())){
*this->pptr()=traits_type::to_char_type(c);
本->pbump(1);
}
返回此->同步()==-1
?特征类型::eof()
:特征类型::非特征类型(c);
}
int-fdbuf::sync(){
如果(this->pbase()!=this->pptr()){
std::streamsize size(this->pptr()-this->pbase());
std::streamsize done(::write(this->fd_,this->exputf_,size));
//下面的代码假设如果流成功
//一些进展。根据需要,可能会更多
合理地认为它是成功的。
//写入整个缓冲区,例如循环几次
//努力取得这一成功。
如果(0<完成){
复制(this->pbase()+完成,this->pptr(),this->pbase());
this->setp(this->pbase(),this->epptr());
此->pbump(大小-完成);
}
}
返回此->pptr()!=此->epptr()?0:-1;
}
int fdbuf::底流()
{
如果(this->gptr()==this->egptr()){
std::streamsize pback(std::min(this->gptr()-this->eback(),
标准:ptrdiff_t(16-sizeof(int));
std::copy(this->egptr()-pback,this->egptr(),this->eback());
int done(::read(this->fd_,this->eback()+pback,bufsize));
this->setg(this->eback(),
此->回退()+pback,
这->回退()+pback+std::max(0,完成));
}
返回this->gptr()==this->egptr()
?特征类型::eof()
:traits_type::to_int_type(*this->gptr());
}
int main()
{
fdbuf-inbuf(0);
std::istream in(&inbuf);
fdbuf(1);
std::ostream out(&F);
std::copy(std::istreambuf_迭代器(in),
std::istreambuf_迭代器(),
std::ostreambuf_迭代器(out));
}

您可以创建自己的类,供streams使用。事实上,如果你稍微搜索一下,有些库已经为你做了这些。你在找吗?更正:这个代码段中有两个bug(它们相互抵消)。调用
overflow()
时,不应写入
*pptr
。您必须先
sync()
,才能腾出空间再次写入。但是,由于第二个问题,
setp
将指针指向最后一个元素,而不是最后一个元素(因此,一旦溢出错误被修复,-1应该被删除)。@BenDarnell:实际上,这两个操作都是经过精心设计的!报告给
setp()
的缓冲区比实际小一个字符,因为此位置将在
overflow()
中用于保存额外字符(如果有)。也就是说,我看不出一个好的理由,为什么溢出字符应该存储在一个空的缓冲区中,而不是与一批缓冲字符一起发送。我很确定,设置缓冲区的流缓冲区不能向其中添加字符(假设它安排了必要的空间)。对pbump(1)的调用将pptr置于从pbase到epptr的范围之外,这是一个错误(导致未定义的行为)。它看起来不像是强制执行的(至少在我正在使用的LBC+++的版本中),但是一个坚持规范的字母的STL实现仍然可以认为这是一个错误。@ BeNARNEL:它当然不是强制执行的,并且标准实际上并没有强制规定<代码>溢出()/<代码>是如何实现的。有一个[次要]值得怀疑的方面,那就是调用
sync()
,而不完全限定流缓冲区类型:理论上,进一步派生的流缓冲区可能会覆盖
sync()
,在这种情况下可能会有问题。当控件被传递到IOStreams库时,指针设置上的约束适用,但在实现特定的流缓冲区时,完全可以对违反约束的情况进行调整。@BenDarnell:查看27.6.3.3[streambuf.put.area]第4段并没有对
pbump()
的参数设置任何先决条件。它的字面意思是“void pbump(int n);Effects:将n添加到输出sequ的下一个指针