Работа с сокетом через std:iostream
От: jagry  
Дата: 24.01.17 11:34
Оценка:
Файл socket.h

#ifndef SOCKET_H
#define SOCKET_H

#include <iostream>

class socketstreambuf :
        public std::streambuf {
    static const std::streamsize bufsize = 1024 ;
    char outbuf_[ bufsize ] ;
    char inbuf_[ bufsize + 16 - sizeof( int ) ] ;
    int handle ;
protected:
    int_type overflow( int_type ) ;
    int_type sync( void ) ;
    int_type underflow( void ) ;
public:
    socketstreambuf( int ) ;
    ~socketstreambuf( void ) ;
    void close( void );
} ;

class iosocketstream :
        public std::iostream {
    socketstreambuf streambuf ;
public :
    iosocketstream( int ) ;
};

#endif


Файл socket.cpp

#include "socket.h"
#include <sys/ioctl.h>
#include <unistd.h>

// iosocketstream

iosocketstream::iosocketstream( int argument ) :
    streambuf( argument ) ,
    std::iostream( &streambuf ) { }

// socketstreambuf

socketstreambuf::socketstreambuf( int argument ) :
    handle( argument ) {
this->setg( this->inbuf_ , this->inbuf_ , this->inbuf_ ) ;
this->setp( this->outbuf_ , this->outbuf_ + bufsize - 1 ) ;
}

socketstreambuf::~socketstreambuf() {
if( pptr( ) != pbase( ) )
    overflow( traits_type::eof( ) ) ;
close( ) ;
}

void socketstreambuf::close( ) {
    if( !( handle < 0 ) )
        sync( ) ,
        ::close( handle ) ;
}

socketstreambuf::int_type socketstreambuf::overflow( int_type c ) {
    std::cout << "Debug: overflow" << std::endl ;
    if (!traits_type::eq_int_type(c, traits_type::eof())) {
        *pptr( ) = traits_type::to_char_type(c);
        pbump(1);
    }
    return this->sync() == -1
        ? traits_type::eof()
        : traits_type::not_eof(c);
}

int socketstreambuf::sync() {
    std::cout << "Debug: sync" << std::endl ;
    if (this->pbase() != this->pptr()) {
        std::streamsize size(this->pptr() - this->pbase());
        std::streamsize done(::write(this->handle, this->outbuf_, size));

        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 ;
}

socketstreambuf::int_type socketstreambuf::underflow( void ) {
    std::cout << "Debug: underflow" << std::endl ;
    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->handle, this->eback() + pback, bufsize));
        u_long nbio = 1;
        ::ioctl(this->handle, FIONBIO, &nbio);
        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());
}


Суть проблемы:
Объявляю сокет-поток:
iosocketstream stream( socket ) ;
чтение из stream(stream.get()) проходит нормально, а вот запись в stream (stream << "Test")не работает
Насколько я понимаю, stream::operator<< должен вызвать socketstreambuf::overflow, но этого не происходит
socketstreambuf streambuf cocket std::streambuf
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.