Re: Sockets: proposal for a library design

Hi Boris, My responses are below...
I would suggest that a proposed Boost.Net library should focus on networking in a more abstract manner, and not be merely a socket encapsulation. IMHO, sockets are a terrible API and should be hidden as fast as possible. A socket wrapper class is appropriate, but I would not go to any trouble to change the socket API. Simply wrap the resources and provide portable access to the underlying system. The real end-user part of the Net library should not talk about sockets (unless one provides a method like get_native to return the socket handle, and that method is defined as non-portable).
This reminds me of the layers requirement from http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl? BoostSocket/SocketRequirements. I agree that it would be nice to have some easy-to-use high-level classes for concepts that are used in network applications again and again.
Yes; sockets are just a means to that end and not the end in themselves. As such, they need not receive much special design consideration because that is not where you want users to interact with the library. A robust socket layer may only encourage undesirable use. The socket layer that has involved in my own code consists of a single Socket class with: a destructor for cleanup, methods that handle the mapping of non-portable EFOOBAR codes to portable exception types or return values, const-correctness, default arguments in a few places, etc.. The network layer simply uses sockets to implement the abstraction, and is the only direct user of sockets.
I agree again. There shouldn't be any of the four I/O models omitted. We will see as we proceed if supporting various I/O models is easy to implement and to use at runtime (especially switching between I/O models).
The I/O model that troubles me is the select/poll model. That is the mechanism I have used to implement the other three and it is not readily apparent how to expose it to the user as well. I may be surprised, but I think most folks would not mind seeing that model go away. The async I/O model with callbacks (essentially made from inside the select/poll/whatever loop) would provide a robust replacement for that tedious body of code.
As others have also suggested, I would agree that the net facilities not be tied up into I/O streams. It would be better to provide the network facilities and then layer on I/O streams for those that want it.
Several people dislike the idea of a network library built on I/O streams. What are the reasons for this?
I can only speak for myself, but I just don't like I/O streams. They seem to have a lot of clunk and little value, IMHO. They may work for text protocols, but in my use of network communications, they don't feel right. For example, the output would probably need consistent flushing do get data out of the buffer and on to the wire.
Is this a request for a more low-level access to socket functions like read(), write(), send() and recv()?
Again, I don't view socket access as the goal, but essentially yes: access to the "primitives" is what I would want. For example, I would want to be able to differentiate EOF from ECONNRESET(?) from ETIMEOUT, etc..
The only reason I see why I/O streams should not be used is the lack of support for an asynchronous I/O model. The network library would have to add functions for asynchronous support
Yes, the network layer has to define what asynchronous I/O looks like. Again, I think a function<> with an appropriate signature is the answer. If the users needs those calls to be queued/marshalled, that is not the problem of the network layer.
until one day I/O streams support an asynchronous I/O model by default (btw, anyone working on this?).
I don't see how I/O streams could be asynchronous because async file I/O is not portable. For example Windows 95/98/Me don't have it. I suspect that many other systems are similar. Even though Windows NT (and 2000, XP, 2K Server) have async file I/O, it is not something that select() can handle as it can on *nix.
Usage examples:
Thanks again! When the socket class hierarchy is more stable I hope to move upwards to high-level classes representing concepts from the network world you used in your examples.
Most welcome. If I recall, the actual number of calls to socket API's made in my entire code base was so few (probably around 10-20) that even the little time I had spent on the socket layer was probably overkill.
One thing I think is essential when using a blocking model is cancellation. For example, I have a reset() method on Acceptor, Address, Datagram and Stream that can be called at any time to cause blocking methods to terminate with a cancel exception (obviously this must be from another thread). Ironically, these reset() methods meant I could not use blocking socket calls to implement my blocking methods - recv() cannot be canceled once it blocks (at least not portably)!
I added this to the Wiki but I am not sure if a network library should support it. If you have two threads in your application and one thread is halted because of a blocking call it might have been better to use a nonblocking/asynchronous I/O model?
Perhaps, but some produces are just best designed as synchronous. They can go along merrily producing data and waiting for it to be consumed before producing more. Eventually they will block, and if they cannot be canceled (forced to unblock), you have a problem. IMO, any mechanism that can block indefinitely really needs some way to cancel. This should not be confused with thread cancellation. In this situation, once a stream is canceled/reset, it is almost completely unusable (most methods will throw the cancel exception). Best, Don __________________________________ Do you Yahoo!? Make Yahoo! your home page http://www.yahoo.com/r/hs
participants (1)
-
Don G