Boost logo

Boost :

From: Pedro Lamarão (pedro.lamarao_at_[hidden])
Date: 2005-06-08 14:18:13

Simon Richter wrote:

> The biggest difference in my implementation is that listeners and
> connected sockets are constructed with a string (of arbitrary character
> type) rather than an address family specific type, i.e. the application
> need not see any types representing addresses. The string is searched
> for a whitespace character, with the portion before it being the address
> family and the remainder the (af specific) address.

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?

> I have tried to get a bit away from the C socket functions, because I
> felt they were not really needed. For example, bind() can be avoided by
> a two-argument form of connect() that binds before connecting (and
> believe me, you do not want to know what #include <sys/socket.h> on
> Solaris does to code that contains the word "bind").

That I didn't know. I'm most of the time in Linux; I've been waiting
eagerly for Fedora Core 4 with it's Xen kernels to install NetBSD and
try the portability of my code.

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.

I'll probably make that class disappear if nothing else stops me.

> The other difference in API is that accepted sockets are extracted from
> the listener, not returned as an auto_ptr. This leads to slight ugliness
> in the implementation (copyfmt() and a set of callbacks) but looks
> really nice in the application source code. I also wonder whether I
> should provide a way to get a "one-shot" listener that will accept a
> single connection and give it as a stream to the application.

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.

I'd be happier to return an "rvalue reference" there, if we already had
such a thing.

I experimented elsewhere with a "socket" class whose copy constructor
and assignment operator "moved" the internal descriptor (leaving the
copied object in an invalid state) to allow such "moving" around of the
object; but it doesn't help the stream classes.

> The thing I am missing in your implementation (but that's also still
> missing in mine :-P) is a wrapper around select() /
> WaitForMultipleObjects() / Wait() / ... along with the ability to run a
> resolver in the background and get a notification on connection
> establishment/failure.

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.

A "select" class would be nice, true, but most of the experiments I've
been doing with this code is multi-threaded, so I haven't actually
needed such a class yet.

But I confess I never truly learned to work with such interfaces.

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...

But as I've stated elsewhere, this library is mostly about IOStreams,
and I've been mostly studying the nice things we can do with operator>>,
operator<<, and streambuf_iterators.

Pedro Lamarão
Intersix Technologies S.A.
SP: (55 11 3803-9300)
RJ: (55 21 3852-3240)
Your Security is our Business

Boost list run by bdawes at, gregod at, cpdaniel at, john at