Boost logo

Boost :

From: Daryle Walker (darylew_at_[hidden])
Date: 2000-12-23 19:35:46


on 12/20/00 7:14 PM, jsberrios_at_[hidden] via boost_at_[hidden] did:

> This email message is a notification to let you know that
> a file has been uploaded to the Files area of the boost
> group.
>
> File : /Socket/Socket.tar.gz
> Uploaded by : jsberrios_at_[hidden]
> Description : Socket library implemented for UNIX/Linux
>
> You can access this file at the URL
>
> http://www.egroups.com/files/boost/Socket/Socket%2Etar%2Egz

I downloaded it at 3:02 PM today (on 21 Dec 2000) to look at it. I don't
know UNIX socket stuff, so these are more general comments.

1. The essential library stuff is all jammed up into one header. Most
other Boost headers do this because they're usually template libraries, and
today's compilers are limited such that user-visible template definitions
must be in header files. If you don't have to do this, like here where
there is lots of non-template code, don't do it. Just move that code to a
*.cpp file. Doing this also helps with problem [2].

2. The solution is extremely UNIX-centric. In fact, isn't it just
guaranteed for two variants (Linux and Solaris)? If you follow the advice
in [1], you could have different *.cpp files, selecting one of them
depending on your platform. This would let you keep only the declarations
and other platform-agnostic parts of the system in the header, and move the
UNIX headers to the *.cpp file. But there's a bigger problem.

3. The problem is also UNIX-centric. It doesn't have any utility for a
non-UNIX system (unless that system can fake UNIX sockets, including
Internet capability). Not good, since the libraries try to be general, at
least in interface. (Point [2] explains handling non-portable
implementations.)

4. A similar problem is to make a stream-buffer class representing an
Internet connection, probably TCP/IP. (I'll get to streams later.) It
could be like std::filebuf, like so:

namespace boost
{
class tcpipbuf
    : public std::streambuf
    , noncopyable
{
public:
    tcpipbuf();
    virtual ~tcpipbuf();

    bool is_open();
    tcpipbuf * open( std::string hostname, uint16_t portnumber );
    tcpipbuf * open( uint32_t hostnumber, uint16_t portnumber );
    tcpipbuf * open( uint8_t (&hostnumbers)[4], uint16_t portnumber );
    tcpipbuf * close();

protected:
    // Place various overrides of basic_streambuf methods here.
    // Note that you don't need to override all of them, as some,
    // like the push-back and repositioning methods, can't be done
    // to TCP/IP connections, so their default implementations of
    // showing immediate failure are fine.

private:
    // Put general connection helper methods here.

    // What it really points to is platform-specific.
    void * tcpip_data_;
};
}

Since IP pushes bytes/octets, I didn't bother specializing for character
type or traits. This also lets me put all the implementation, including the
type of data that 'tcpip_data_' secretly holds, in the source (*.cpp) file.
There can be one source file per platform, and the user has to add the right
one to the project, or all versions can be in one file, separated by
platform-specific macros.

5. For IOStreams, there are two main class branches, representing the
different concepts of formatting the data and of connecting to the real
world. The streambuf classes are the connection from raw character data to
the source/sink the data comes from or goes to. The stream classes control
the formatting. You tried to do both in one class. Don't merge them; it's
confusing to create, to understand, and to interact it with other C++ stuff.
Now the next part is to make stream classes that use an internal object of
your new streambuf class.

namespace boost
{
namespace detail
{
class tcpipbuf_helper
{
public:
    // These methods are passed to the 'ron_' member
    bool is_open();
    void open( std::string hostname, uint16_t portnumber );
    void open( uint32_t hostnumber, uint16_t portnumber );
    void open( uint8_t (&hostnumbers)[4], uint16_t portnumber );
    void close();

    tcpipbuf const * get_buffer() const
        { return &ron_; }

private:
    friend class ::boost::itcpipstream;
    friend class ::boost::otcpipstream;
    friend class ::boost::tcpipstream;

    tcpipbuf_helper()
        {}
    ~tcpipbuf_helper()
        {}

    tcpipbuf ron_;
};
} // detail

class itcpipstream
    : public detail::tcpipbuf_helper
    , public std::istream
{
    itcpipstream()
        : std::istream( &(this->detail::tcpipbuf_helper::ron_) )
        {}
};

class otcpipstream
    : public detail::tcpipbuf_helper
    , public std::ostream
{
    otcpipstream()
        : std::ostream( &(this->detail::tcpipbuf_helper::ron_) )
        {}
};

class tcpipstream
    : public detail::tcpipbuf_helper
    , public std::iostream
{
    tcpipstream()
        : std::iostream( &(this->detail::tcpipbuf_helper::ron_) )
        {}
};
} // boost

-- 
Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk