From: Simon Richter (Simon.Richter_at_[hidden])
Date: 2005-06-09 10:39:57
Pedro LamarÃ£o wrote:
> How do you interpret the results of name resolution and pass that to the
> "connect" and "bind" equivalents? Do the "client" and "listener" classes
> automatically call the resolver?
Yes, that is the plan (name resolution is not implemented yet). A socket
stream can be constructed with an optional reference to a "manager"
class (which is the select() wrapper, basically), which holds a set of
resolvers (similar to locale facets). If a manager object is given, it
is asked for a resolver, which is given the query and a method to call
on completion, then control is transferred back to the caller. If no
manager object is given, a resolver is instantiated, the name resolved
and the resolver destroyed (=> you need a manager for nonblocking I/O).
The resolver is usually called by the manager when the application
enters its idle loop, so applications may not wait for connections to
get established when they use a manager object.
> But the need for the existence of a "socket" class is questionable; the
> IO primitive in the C++ standard library is the streambuf; ugly or not,
> it provides a complete "client" for a networking library.
My streambufs hold a pointer to an abstract "impl" class which
represents the actual socket. Concrete subclasses of that exist for
different socket types, so new address families can be added at runtime
(currently, only through my plugin interface, which I wrote about to the
list a few days ago).
> That auto_ptr is there because stream objects are not copyable, and the
> purpose of that "listener" is to internalize the "accept" primitive and
> the stream constructor.
They are not copy-constructible, that is different from not copiable
:-). A new streambuf can be attached to an existing stream, as long as
care is taken to properly destroy the streambuf on stream close).
> I'd be happier to return an "rvalue reference" there, if we already had
> such a thing.
Hrm, they could be made copy-constructible, I think, the benefit of that
would however be questionable.
> In the example/ directory of the socketstream project, check out the
> asynch_resolver.h file; there's an asynchronous version of the resolver
> class there implemented using boost::thread.
I avoid spawning new threads from library functions like the plague, as
it is difficult to properly collect those threads in case of an
> I suspect there's little hope of doing anything different than keeping a
> std::vector or std::list of whatever networking object we're holding,
> and creating the proper structure for select() or poll() when calling
> the blocker method. That might make the blocker method O(n) on the
> number of networking objects...
I think the manager object should have a list of pointers to the streams
it monitors and have a callback registered with them so the stream is
scheduled for removal on stream destruction (we cannot unregister the
stream right away as there might be iterators in the list of pointers
that we'd invalidate).
I think we should attempt to coordinate our efforts here.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk