Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / September 2007

Tip: Looking for answers? Try searching our database.

API Design: Is Socket.Select() seriously busted?

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Dilip - 27 Sep 2007 22:55 GMT
I don't know how I missed this piece for so long (this may also be old
news to you guys) but in this ACMQueue article, Michi Henning goes to
elaborate lengths to detail how even today designing a good API
requires a lot experience and effort by illustrating the example of
something as common place as the select() function call available in
sockets.  The example focuses on the design decision surrounding the
Select() call in C#.

It comes under the heading "Bad APIs are easy" and goes on for about 4
pages about its problems.

The link to the article is here:
http://www.acmqueue.com/modules.php?name=Content&pa=showpage&pid=488&page=1

What do the experts think?
Ben Voigt [C++ MVP] - 27 Sep 2007 23:16 GMT
> I don't know how I missed this piece for so long (this may also be old
> news to you guys) but in this ACMQueue article, Michi Henning goes to
[quoted text clipped - 11 lines]
>
> What do the experts think?

Socket.Select isn't meant to be a good, modern API, it is meant to emulate
Berkely Sockets' select() function.  It looks like it does that quite well.

The suggested improvements are a big step forward from select, but pale
horribly beside event-driven programming (WSAEventSelect or WSAAsyncSelect
or a completion port which in .NET means asynchronous BeginXYZ calls with a
WaitHandle or a completion callback delegate).

Overall, Socket.Select isn't meant to be the .NET way, it's meant to ease
porting code that already uses BSD select().
Michi Henning - 28 Sep 2007 23:23 GMT
> Socket.Select isn't meant to be a good, modern API, it is meant to emulate
> Berkely Sockets' select() function.  It looks like it does that quite well.

Hmmm... I would disagree with that. The .NET Select() adds the
following errors on top of the (already poor) design of the C version
of select():

- It does not allow the caller to wait in definitely (in .NET 1.1)

- It does not allow the caller to set a timeout longer than 35 minutes

- It makes it difficult to distinguish whether it returns because of a
timeout or because a
 socket is read because the return type is void.

- It allows the caller to pass duplicate sockets because the
parameters a lists, not sets.

- It has ambiguous input and output values because any of the socket
lists can be null or
 be an empty list.

So, as far as emulating the original is concerned, I think Select()
does quite a poor job.

> The suggested improvements are a big step forward from select, but pale
> horribly beside event-driven programming (WSAEventSelect or WSAAsyncSelect
> or a completion port which in .NET means asynchronous BeginXYZ calls with a
> WaitHandle or a completion callback delegate).

Of course the improvements I suggested are not the bees' knees of
Select() and, as I said in the article, the point wasn't to come up
with the ultimate version of select (other people have done that
already--I mentioned epoll() as an example); the point was to show how
a few seemingly small errors quickly pile up to cause a lot of grief.

> Overall, Socket.Select isn't meant to be the .NET way, it's meant to ease
> porting code that already uses BSD select().

Well, having done exactly that, namely ported code that already used
BSD select(), I can definitely state that .NET Select() fails to ease
porting such code quite spectacularly.

Cheers,

Michi.
Michael Rubinstein - 28 Sep 2007 15:18 GMT
Dilip, the article does not focus on just the unfortunate design of the
select() function. It uses it as an example. The part of the article I liked
most, is where the author condemns the API forcing the developer using error
trapping for intercepting error that should not be anticipated. In .NET
Socket class the async callback function will throw an error whenever the
connection is lost. This was discussed in this NG quite a few times and the
'experts' here see nothing wrong with relying on error trapping mechanism.
The author of the article calls the API design that encourages such
practices 'perverse', and I agree. There are similar snafus in .NET Serial
class. USB-Serial converters are very common and work quite well. The
problem is, if the user pulls the USB connector out while the 'mapped' com
port was open, there is no way the application can handle this situation,
even error trapping is not a solution. Very good article, thanks for posting
the link.

   Michael

> I don't know how I missed this piece for so long (this may also be old
> news to you guys) but in this ACMQueue article, Michi Henning goes to
[quoted text clipped - 11 lines]
>
> What do the experts think?
Michi Henning - 28 Sep 2007 23:27 GMT
On Sep 29, 12:18 am, "Michael Rubinstein"
<mSPAM_REMOVEr@m?ubinstein.com> wrote:
>     The part of the article I liked
> most, is where the author condemns the API forcing the developer using error
> trapping for intercepting error that should not be anticipated.

There are tons of APIs around that throw exceptions when they
shouldn't. And, invariably, when they do, it causes grief for the
caller.

> The author of the article calls the API design that encourages such
> practices 'perverse', and I agree.

I don't recall using this term in that context. Not that I'd disagree
though. Asynchrnous reads from a .NET socket do exactly this: throw an
exception when for the expected outcome (namely, no data ready to
read), and return zero for the unexpected outcome (namely, connection
loss). Code that has to deal with this nonsense ends up looking very
contorted because of the mess of control flow.

Cheers,

Michi.
Michael Rubinstein - 29 Sep 2007 05:26 GMT
Michi,

I don't recall using this term in that context.

on page 5 you wrote:
(Another popular design flaw-namely, throwing exceptions for expected
outcomes-also causes inefficiencies because catching and handling exceptions
is almost always slower than testing a return value.)

This was what you wrote. What I ment, is that code like below - pasted
directly from VS2005 help for Socket class:

public static void Read_Callback(IAsyncResult ar){
    StateObject so = (StateObject) ar.AsyncState;
    Socket s = so.workSocket;

    int read = s.EndReceive(ar);

    if (read > 0) {
           so.sb.Append(Encoding.ASCII.GetString(so.buffer, 0, read));
           s.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0,
                                   new
AsyncCallback(Async_Send_Receive.Read_Callback), so);
    }
    else{
        if (so.sb.Length > 1) {
             //All of the data has been read, so displays it to the console
             string strContent;
             strContent = so.sb.ToString();
             Console.WriteLine(String.Format("Read {0} byte from socket" +
                               "data = {1} ", strContent.Length, strContent));
        }
        s.Close();
    }
}is guaranteed to crash when the connection is lost, or the other side
disconnects forcefully, unless the code is wrapped into try/catch. Under
Win32 Winsock there was no need for using error trapping when responding to
socket events because WSAAsyncSelect() takesthe handle of the window
receiving notifications. .NET Sockets do not offer any means to notify the
application when the socket is aboutto 'bite the dust'. So we are using
error trapping for handling predictable situations. The sad thing, it is
easy to get used to.    Michael
On Sep 29, 12:18 am, "Michael Rubinstein"
<mSPAM_REMOVEr@m®ubinstein.com> wrote:
>     The part of the article I liked
> most, is where the author condemns the API forcing the developer using
> error
> trapping for intercepting error that should not be anticipated.

There are tons of APIs around that throw exceptions when they
shouldn't. And, invariably, when they do, it causes grief for the
caller.

> The author of the article calls the API design that encourages such
> practices 'perverse', and I agree.

I don't recall using this term in that context. Not that I'd disagree
though. Asynchrnous reads from a .NET socket do exactly this: throw an
exception when for the expected outcome (namely, no data ready to
read), and return zero for the unexpected outcome (namely, connection
loss). Code that has to deal with this nonsense ends up looking very
contorted because of the mess of control flow.

Cheers,

Michi.
Michi Henning - 29 Sep 2007 23:45 GMT
On Sep 29, 2:26 pm, "Michael Rubinstein"
<mSPAM_REMOVEr@m?ubinstein.com> wrote:
>     Michi,
>
[quoted text clipped - 6 lines]
>
> This was what you wrote.

Right. I didn't say "perverse" there, although I would say that's an
apt description :-)

> .NET Sockets do not offer any means to notify the
> application when the socket is aboutto 'bite the dust'. So we are using
> error trapping for handling predictable situations. The sad thing, it is
> easy to get used to.

Yes, Depressing, really. Things like this are a clear indication that
the API design never ate his own dog food...

Cheers,

Michi.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.