Extension Methods and SocketAsyncEventArgs

SocketAsyncEventArgs

The System.Net.Sockets namespace is one of the many in .NET 3.5 to have a bit of an overhall. There are enhancements to the Socket class itself and also a new class, SocketAsyncEventArgs. The enhancements are designed for use in applications which require performance and scalability during massively high volume asyncronous socket I/O.

There are several areas in writing a socket server where bottlenecks can be introduced. The most severe is caused by .NET pinning your buffers as they're passed to winsock functions which can cause your application to crash with an OutOfMemoryException even though it actually isn't, there's a great explanation of the problem in a blog post by Yun Jin which can be found here. The second common issue is the use of the APM in high volume scenarios which leads to an IAsyncResult object being allocated for every operation, obviously not the best solution and a little hard on the GC.

This is where SocketAsyncEventArgs comes in, along with a new pattern for asyncronous operations in the Socket class. The basic gist is that your code gets to declare and instantiate these objects, unlike IAsyncResult which is created for you, and as such they can be pooled and reused.

Great! What's that got to do with Extension Methods?

Well, this new pattern (the third in .NET now!) for asyncronous operation is kind of funky looking. Basically, you create your SocketAsyncEventArgs, attach a handler to it's Completed event and then pass it into one of Socket's new "xxxAsync" methods. All Fairly straight forward, the operation completes (or doesn't!) and your callback is invoked. The catch, and the aforementiond funkyness is that if the operation actually completes synchronously then "xxxAsync" returns false and your callback is not invoked!

The MSDN sample illustrates how they deal with this (surrounding code removed):

private void StartAccept(SocketAsyncEventArgs acceptEventArg)

{

    bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg);

    if (!willRaiseEvent)

    {

        ProcessAccept(acceptEventArg);

    }

}

 

private void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)

{

    ProcessAccept(e);

}

 

private void ProcessAccept(SocketAsyncEventArgs e)

{

    //...

}

Pretty ugly, right? Well trust me, when it's intertwined with the rest of your socket/threading code it's a mess. Enter Extension Methods!

internal delegate Boolean SocketAsyncMethod(SocketAsyncEventArgs args);

 

internal static class AsyncSocketMethodHelper

{

    public static void InvokeAsyncMethod(this Socket socket, SocketAsyncMethod method,

        EventHandler<SocketAsyncEventArgs> callback, SocketAsyncEventArgs args)

    {

        if (!method(args))

            callback(socket, args);

    }

}

Now our code to accept a new socket looks like this:

public void StartAccept(SocketAsyncEventArgs acceptEventArg)

{

    listenSocket.InvokeAsyncMethod(listenSocket.AcceptAsync,

        AcceptEventArg_Completed,

        acceptEventArg);

}

 

private void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)

{

    //...

}

Well I like it anyway! My Extension Methods are in their own namespace and are marked internal, just a convenience for me while I write my socket server, can't hurt anyone else!

There will be more posts coming about my socket server adventures...

kick it on DotNetKicks.com  

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList
December 18, 2007 13:17 by Sean
E-mail | Permalink | Comments (1) | Comment RSSRSS comment feed

Related posts

Comments

December 18. 2007 23:14

Trackback from DotNetKicks.com

Extension Methods and SocketAsyncEventArgs

DotNetKicks.com

Comments are closed