Boost logo

Boost :

From: Rob Lievaart (Rob.Lievaart_at_[hidden])
Date: 2003-10-27 04:55:32


Hi Jessie,

Some quick feedback, I haven't actually tried to use it.
In general I think a socket framework would be usefull,
but as you can see in the vault a lot of people have tried,
and non has succeeded so far.

> I'd like to get feedback on the current state of the library
> and see what
> can be improved (I'm mostly interested in the design aspect).
Which is not documented, so hard to comment on. :-)

- I like the idea of having streams, that can wrap around sockets,
  they can make it easy to use sockets in a lot of places.

- ipv4 vs. ipv6
   From what I understand, to talk to a host I need to do something like
   this:

      typedef ipv4_domain domain;
      domain::address_type addr( host<domain>( "www.boost.org"
).address().ip(), 80 );
      connector<domain> conn;
      basic_socketstream<domain, char> sockstream( "stream:tcp" );
      ...

   This means that my code is locked to ipv4, should boost ever become
   reachable via ipv6 then I'll still use ipv4 and if that is ever
   dropped I'm out of luck.

   Sometimes you want to be able to specify exactly what protocol to use,
but
   usually, I don't care. It would be nice if the library could handle this
   so in the default case I don't have to think about it and my program
   will work with both ipv6 and ipv4 hosts/clients. (if and when available)

   (In Unix Network Programming, W. Richard Stevens describes some C wrapper
   functions that lets you treat IPV4, IPV6, and Unix domain sockets, more
   or less transparently)

   Also I wonder if the domain really needs to be a parameter everywhere.
   IIRC, the only difference at the level of the socket api is
   size fo the address structure being passed around, and the handling
   of gethostbyname/getaddrinfo functions. And some extra coket options.

   I expect it is possible to make most of the library unaware of the
existence
   of the different domains. Probably only the address_type needs to be
aware
   that differences exist, but it could hide it from most of the library
   and from the user.

- I see a connector , I assume there will also be an acceptor
   to accompany the "server_socket"? I am still not to comfortable with
   the connector/acceptor idea. Acceptors have to do some work, listen
   on a socket, create a new one, etc. so it makes some sense to create
   a seperate object for that. And then a connector looks good with that,
   but a whole object just for a call to
      ::connect( ... )
   feels kind of overdoing it to me.
   (I know loads of people disagree with me, I just thought I'd mention it.)

- Exceptions:
   You have a large exception hierarchy. There has been some debate on the
use
   of large exception hierarchies versus a single exception with error
codes.
   I am not sure if there was a winner, but personnally I would prefer a
single
   socket exception with errorcodes.
   You currently have 20 or so exception classes and they are members of
either
   the socket_base or the host_base _class_ instead of boost::net or where
ever
   the library would live.

- Host class
   Here you also have the domain ipv4,ipv6 in the type, but a host could
   have both an ipv4 and ipv6 stack, and AFAIK most current host that have
   IPV6 also have an ipv4 stack. So in this case, the address list of
   a host would contain ipv4 and ipv6 addresses.

- I wonder what the use of the abstract base classes domain_base and
   address_base is. It looks to me like you only use their subclasses
   in templates and never plymorphically, so why would you make a
   baseclass with virtual functions?

- Why the split into basic_socket and basic_socket implementation,
   what is the use of that? All the members of basic_socket_impl
   are virtual, but I don't see any case of wanting to replace this
   with something else at runtime.
   It looks to me like you are using it to share implementation between
   basic_socket and server_socket, but wouldn't it be easier to
   do this using a common baseclass. I could have missed it but
   I see no use for the seperate implementation class.

Some implementation issues:

- You like to use underscores in variable names, names starting with
   double underscores, or starting with an underscore and all caps are
   reserved. They could clash with compiler defined names, so you
   should avoid them. Take a look at:
   
    http://oakroadsystems.com/tech/cppredef.htm

- I see quite a few ifdefs related to the socklen_t type,
   e.g.:

    #if defined( WIN32 )
        int _NameLength = sizeof( address_type::native_t );
    #else
        socklen_t _NameLength = sizeof( address_type::native_t );
    #endif

   These could be replaced by a single typedef somewhere. Makes
   the code a lot simpler.

- The shutdown function taking an ios_base::openmode as parameter
   seems strange.

- It would be nice if the connector also accepted socket streams, instead
   of needing to pass stream->rdsocket(). Also I am not sure if you want to
   expose the socket at this level, the socket streams wrap a buffer that
wraps
   a socket, so maybe rdbuf should be enough here, from there you can
   go to the socket, iff required.

Just my $0.02,

Rob Lievaart.


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