Click here to Skip to main content
13,259,986 members (52,096 online)
Click here to Skip to main content
Add your own
alternative version


121 bookmarked
Posted 14 Jan 2008

How To Use the SocketAsyncEventArgs Class

, 29 Sep 2010
Rate this:
Please Sign up or sign in to vote.
An article about how to use the SocketAsyncEventArgs class


I was looking for a high performance code for a client socket. Previously, I wrote a code based on the traditional asynchronous programming model methods from the Socket class (BeginSend, BeginReceive, and so on). But it didn't fill the performance requirements I needed. Then, I found the new model for event-based asynchronous operations (see "Get Connected with the .NET Framework 3.5" in the September 2007 issue of the MSDN Magazine).


The Asynchronous Programming Model (APM) is used widely in I/O-bound applications to achieve high performance, due to the reduction of blocking threads. APM is implemented in the .NET Framework since its first version, and is improving since then, using new techniques like lambda expressions from C# 3.0. Specifically for socket programming, the new model for APM delivers an easier coding, not to mention the performance benefits. It is done towards the use of the SocketAsyncEventArgs class to keep the context between I/O operations, which reduces object allocation and the garbage collection working.

The SocketAsyncEventArgs class is also available in the .NET Framework 2.0 SP1, and the code from this article was written using Microsoft Visual Studio .NET 2008.

Using the Code

To begin with the SocketAsyncEventArgs class, I studied the example from MSDN, but there was something missing: the AsyncUserToken class. I understood the class should expose a property Socket, corresponding to the socket used to perform the I/O operations. But how to keep data received from client until the accept operation ends? Since UserToken is an Object, it could accept anything, so I created a Token class to track the accept operation. Below shown are the modified methods to use the instance of Token class as the UserToken.

// Process the accept for the socket listener.
private void ProcessAccept(SocketAsyncEventArgs e)
    Socket s = e.AcceptSocket;
    if (s.Connected)
            SocketAsyncEventArgs readEventArgs = this.readWritePool.Pop();
            if (readEventArgs != null)
                // Get the socket for the accepted client connection and put it into the 
                // ReadEventArg object user token.
                readEventArgs.UserToken = new Token(s, this.bufferSize);

                Interlocked.Increment(ref this.numConnectedSockets);
                Console.WriteLine("Client connection accepted. 
			There are {0} clients connected to the server",

                if (!s.ReceiveAsync(readEventArgs))
                Console.WriteLine("There are no more available sockets to allocate.");
        catch (SocketException ex)
            Token token = e.UserToken as Token;
            Console.WriteLine("Error when processing data received from {0}:\r\n{1}", 
			token.Connection.RemoteEndPoint, ex.ToString());
        catch (Exception ex)

        // Accept the next connection request.

// This method is invoked when an asynchronous receive operation completes. 
// If the remote host closed the connection, then the socket is closed.
// If data was received then the data is echoed back to the client.
private void ProcessReceive(SocketAsyncEventArgs e)
    // Check if the remote host closed the connection.
    if (e.BytesTransferred > 0)
        if (e.SocketError == SocketError.Success)
            Token token = e.UserToken as Token;

            Socket s = token.Connection;
            if (s.Available == 0)
                // Set return buffer.
                if (!s.SendAsync(e))
                    // Set the buffer to send back to the client.
            else if (!s.ReceiveAsync(e))
                // Read the next block of data sent by client.

// This method is invoked when an asynchronous send operation completes.
// The method issues another receive on the socket to read any additional 
// data sent from the client.
private void ProcessSend(SocketAsyncEventArgs e)
    if (e.SocketError == SocketError.Success)
        // Done echoing data back to the client.
        Token token = e.UserToken as Token;
        if (!token.Connection.ReceiveAsync(e))
            // Read the next block of data send from the client.

I also modified the code to show where you can manipulate the message received by the listener. In the example, I created the method ProcessData in the Token class to echoing back to the client the received message.

To control the listener lifetime, an instance of the Mutex class is used. The Start method, which is based on the original Init method creates the mutex, and the corresponding Stop method releases the mutex. These methods are suitable to implement the socket server as a Windows Service.

// Starts the server such that it is listening
// for incoming connection requests.
internal void Start(Int32 port)
    // Get host related information.
    IPAddress[] addressList = 
    // Get endpoint for the listener.
    IPEndPoint localEndPoint = 
          new IPEndPoint(addressList[addressList.Length - 1], port);

    // Create the socket which listens for incoming connections.
    this.listenSocket = new Socket(localEndPoint.AddressFamily, 
                        SocketType.Stream, ProtocolType.Tcp);

    if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
        // Set dual-mode (IPv4 & IPv6) for the socket listener.
        // 27 is equivalent to IPV6_V6ONLY socket
        // option in the winsock snippet below,
        // based on
        //   creating-ip-agnostic-applications-part-2-dual-mode-sockets.aspx
                                         (SocketOptionName)27, false);
        this.listenSocket.Bind(new IPEndPoint(IPAddress.IPv6Any, 
        // Associate the socket with the local endpoint.

    // Start the server.

    // Post accepts on the listening socket.


// Stop the server.
internal void Stop()

Now that we have a socket server, the next step is to create a socket client using the SocketAsyncEventArgs class. Although the MSDN says that the class is specifically designed for network server applications, there is no restriction in using this APM in a client code. Below, there is the SocketClien class, written in this way:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace SocketAsyncClient
    // Implements the connection logic for the socket client.
    internal sealed class SocketClient : IDisposable
        // Constants for socket operations.
        private const Int32 ReceiveOperation = 1, SendOperation = 0;

        // The socket used to send/receive messages.
        private Socket clientSocket;

        // Flag for connected socket.
        private Boolean connected = false;

        // Listener endpoint.
        private IPEndPoint hostEndPoint;

        // Signals a connection.
        private static AutoResetEvent autoConnectEvent = 
                              new AutoResetEvent(false); 

        // Signals the send/receive operation.
        private static AutoResetEvent[] 
                autoSendReceiveEvents = new AutoResetEvent[]
            new AutoResetEvent(false),
            new AutoResetEvent(false)

        // Create an uninitialized client instance.
        // To start the send/receive processing call the
        // Connect method followed by SendReceive method.
        internal SocketClient(String hostName, Int32 port)
            // Get host related information.
            IPHostEntry host = Dns.GetHostEntry(hostName);

            // Address of the host.
            IPAddress[] addressList = host.AddressList;

            // Instantiates the endpoint and socket.
            hostEndPoint = 
              new IPEndPoint(addressList[addressList.Length - 1], port);
            clientSocket = new Socket(hostEndPoint.AddressFamily, 
                               SocketType.Stream, ProtocolType.Tcp);

        // Connect to the host.
        internal void Connect()
            SocketAsyncEventArgs connectArgs = new SocketAsyncEventArgs();

            connectArgs.UserToken = clientSocket;
            connectArgs.RemoteEndPoint = hostEndPoint;
            connectArgs.Completed += 
               new EventHandler<socketasynceventargs />(OnConnect);


            SocketError errorCode = connectArgs.SocketError;
            if (errorCode != SocketError.Success)
                throw new SocketException((Int32)errorCode);

        /// Disconnect from the host.
        internal void Disconnect()

        // Calback for connect operation
        private void OnConnect(object sender, SocketAsyncEventArgs e)
            // Signals the end of connection.

            // Set the flag for socket connected.
            connected = (e.SocketError == SocketError.Success);

        // Calback for receive operation
        private void OnReceive(object sender, SocketAsyncEventArgs e)
            // Signals the end of receive.

        // Calback for send operation
        private void OnSend(object sender, SocketAsyncEventArgs e)
            // Signals the end of send.

            if (e.SocketError == SocketError.Success)
                if (e.LastOperation == SocketAsyncOperation.Send)
                    // Prepare receiving.
                    Socket s = e.UserToken as Socket;

                    byte[] receiveBuffer = new byte[255];
                    e.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
                    e.Completed += 
                      new EventHandler<socketasynceventargs />(OnReceive);

        // Close socket in case of failure and throws
        // a SockeException according to the SocketError.
        private void ProcessError(SocketAsyncEventArgs e)
            Socket s = e.UserToken as Socket;
            if (s.Connected)
                // close the socket associated with the client
                catch (Exception)
                    // throws if client process has already closed
                    if (s.Connected)

            // Throw the SocketException
            throw new SocketException((Int32)e.SocketError);

        // Exchange a message with the host.
        internal String SendReceive(String message)
            if (connected)
                // Create a buffer to send.
                Byte[] sendBuffer = Encoding.ASCII.GetBytes(message);

                // Prepare arguments for send/receive operation.
                SocketAsyncEventArgs completeArgs = new SocketAsyncEventArgs();
                completeArgs.SetBuffer(sendBuffer, 0, sendBuffer.Length);
                completeArgs.UserToken = clientSocket;
                completeArgs.RemoteEndPoint = hostEndPoint;
                completeArgs.Completed += 
                  new EventHandler<socketasynceventargs />(OnSend);

                // Start sending asynchronously.

                // Wait for the send/receive completed.

                // Return data from SocketAsyncEventArgs buffer.
                return Encoding.ASCII.GetString(completeArgs.Buffer, 
                       completeArgs.Offset, completeArgs.BytesTransferred);
                throw new SocketException((Int32)SocketError.NotConnected);

        #region IDisposable Members

        // Disposes the instance of SocketClient.
        public void Dispose()
            if (clientSocket.Connected)


Points of Interest

I had an experience with a socket server running in a clustered environment. In this scenario, you can't use the first entry in the address list from the host. Instead, you should use the last address, as shown in the Start method. Another technique presented here is how to set the dual mode for an IP6 address family, which is helpful if you want to run the server in a Windows Vista or Windows Server 2008, which enables IP6 by default.

Both programs use command-line arguments to run. In the client example, you should inform "localhost" as the name of the host instead of the machine name if both the server and the client are running in a machine out of a Windows domain.


  • 15 January, 2008 - Original version posted
  • 28 September, 2010 - Updated article and server example


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Marcos Hidalgo Nunes
Brazil Brazil
I am working with software development since 1989, mainly in distributed environments.

You may also be interested in...


Comments and Discussions

Questiondid you wrote and shared code about: FlawlessCode.Network.ExtensionMethods Pin
jqb24-Sep-17 22:27
memberjqb24-Sep-17 22:27 
QuestionI consult you about socket, please. Pin
jqb21-May-17 22:53
memberjqb21-May-17 22:53 
QuestionIs this possible also for UDP? Pin
ronconsoda23-Apr-16 23:33
memberronconsoda23-Apr-16 23:33 
PraiseApppreciation on Excellent understanding of socketeventargs class Pin
Member 109465607-Mar-16 12:47
memberMember 109465607-Mar-16 12:47 
SuggestionMy vote of 5 with a slight change for the client buffer size being exceeded. Pin
dja7424-Apr-15 6:54
memberdja7424-Apr-15 6:54 
QuestionHow to keep the access request to the server by the client when server program is terminated abruptly? Pin
Member 1107355025-Sep-14 23:04
memberMember 1107355025-Sep-14 23:04 
QuestionToken.ProcessData can't read all the bytes from client. Pin
Member 1073872910-Apr-14 0:21
memberMember 1073872910-Apr-14 0:21 
GeneralMy vote of 5 Pin
forgetyouyou17-Jul-13 4:23
memberforgetyouyou17-Jul-13 4:23 
GeneralMy vote of 5 Pin
reachen13-Apr-13 7:17
memberreachen13-Apr-13 7:17 
thanks for share and your time to share it.
it's very goole.
QuestionCompleting Data Sent and Timeout Pin
Wendell M.4-Jan-13 20:55
memberWendell M.4-Jan-13 20:55 
QuestionVery good Pin
Luiz Salamon10-Dec-12 1:27
memberLuiz Salamon10-Dec-12 1:27 
AnswerRe: Very good Pin
Marcos Hidalgo Nunes10-Dec-12 14:26
memberMarcos Hidalgo Nunes10-Dec-12 14:26 
QuestionMemory leak Pin
korrea805-Sep-12 7:04
memberkorrea805-Sep-12 7:04 
AnswerRe: Memory leak Pin
Marcos Hidalgo Nunes5-Sep-12 15:23
memberMarcos Hidalgo Nunes5-Sep-12 15:23 
GeneralRe: Memory leak Pin
korrea805-Sep-12 22:36
memberkorrea805-Sep-12 22:36 
GeneralRe: Memory leak Pin
Marcos Hidalgo Nunes11-Sep-12 15:52
memberMarcos Hidalgo Nunes11-Sep-12 15:52 
GeneralRe: Memory leak Pin
Bukan iJam8-Feb-14 23:20
memberBukan iJam8-Feb-14 23:20 
GeneralRe: Memory leak Pin
Marcos Hidalgo Nunes10-Feb-14 13:33
memberMarcos Hidalgo Nunes10-Feb-14 13:33 
GeneralRe: Memory leak Pin
Bukan iJam12-Feb-14 0:51
memberBukan iJam12-Feb-14 0:51 
QuestionSending data without receiving? Pin
nickelm3-Sep-12 0:53
membernickelm3-Sep-12 0:53 
AnswerRe: Sending data without receiving? Pin
Marcos Hidalgo Nunes3-Sep-12 14:54
memberMarcos Hidalgo Nunes3-Sep-12 14:54 
GeneralRe: Sending data without receiving? Pin
nickelm3-Sep-12 23:36
membernickelm3-Sep-12 23:36 
GeneralRe: Sending data without receiving? Pin
Marcos Hidalgo Nunes4-Sep-12 15:53
memberMarcos Hidalgo Nunes4-Sep-12 15:53 
GeneralRe: Sending data without receiving? Pin
nickelm4-Sep-12 20:00
membernickelm4-Sep-12 20:00 
Questionhow to code a server base on SocketAsyncEventAgrs Echo multiple clients? Pin
lvyuqiang29-May-12 0:57
memberlvyuqiang29-May-12 0:57 
AnswerRe: how to code a server base on SocketAsyncEventAgrs Echo multiple clients? Pin
Marcos Hidalgo Nunes29-May-12 17:41
memberMarcos Hidalgo Nunes29-May-12 17:41 
GeneralRe: how to code a server base on SocketAsyncEventAgrs Echo multiple clients? Pin
lvyuqiang29-May-12 18:54
memberlvyuqiang29-May-12 18:54 
GeneralRe: how to code a server base on SocketAsyncEventAgrs Echo multiple clients? Pin
Marcos Hidalgo Nunes5-Jun-12 16:02
memberMarcos Hidalgo Nunes5-Jun-12 16:02 
GeneralRe: how to code a server base on SocketAsyncEventAgrs Echo multiple clients? Pin
lvyuqiang12-Jun-12 19:05
memberlvyuqiang12-Jun-12 19:05 
QuestionIs this still the best approach? Pin
Paul Tait6-Oct-11 16:03
memberPaul Tait6-Oct-11 16:03 
GeneralI have one question Pin
Member 78137425-Apr-11 5:16
memberMember 78137425-Apr-11 5:16 
GeneralRe: I have one question Pin
Marcos Hidalgo Nunes5-Apr-11 18:00
memberMarcos Hidalgo Nunes5-Apr-11 18:00 
GeneralRe: I have one question Pin
Member 78137425-Apr-11 23:27
memberMember 78137425-Apr-11 23:27 
GeneralRe: I have one question Pin
Marcos Hidalgo Nunes7-Apr-11 14:53
memberMarcos Hidalgo Nunes7-Apr-11 14:53 
GeneralCrash after 1300 connections Pin
DJAlexxstyle21-Mar-11 9:06
memberDJAlexxstyle21-Mar-11 9:06 
GeneralRe: Crash after 1300 connections Pin
Marcos Hidalgo Nunes21-Mar-11 15:26
memberMarcos Hidalgo Nunes21-Mar-11 15:26 
GeneralRe: Crash after 1300 connections [modified] Pin
DJAlexxstyle22-Mar-11 10:52
memberDJAlexxstyle22-Mar-11 10:52 
GeneralRe: Crash after 1300 connections [modified] Pin
meraydin6-May-12 21:47
membermeraydin6-May-12 21:47 
GeneralMy vote of 5 Pin
SteveWilkinson21-Dec-10 23:30
memberSteveWilkinson21-Dec-10 23:30 
QuestionSSL with SocketAsyncEventArgs? Pin
jcexited6-Oct-10 21:55
memberjcexited6-Oct-10 21:55 
AnswerRe: SSL with SocketAsyncEventArgs? Pin
Marcos Hidalgo Nunes7-Oct-10 17:14
memberMarcos Hidalgo Nunes7-Oct-10 17:14 
GeneralRe: SSL with SocketAsyncEventArgs? Pin
Metal_GOD13-Dec-10 7:57
memberMetal_GOD13-Dec-10 7:57 
GeneralRe: SSL with SocketAsyncEventArgs? Pin
Marcos Hidalgo Nunes13-Dec-10 15:31
memberMarcos Hidalgo Nunes13-Dec-10 15:31 
GeneralWhere to Process the incoming message and respond indepenently for each client Pin
nickvh6-Oct-10 7:52
membernickvh6-Oct-10 7:52 
GeneralRe: Where to Process the incoming message and respond indepenently for each client Pin
Marcos Hidalgo Nunes7-Oct-10 17:25
memberMarcos Hidalgo Nunes7-Oct-10 17:25 
Generaliocp socket server Pin
VF8-Sep-10 23:43
memberVF8-Sep-10 23:43 
GeneralRe: iocp socket server Pin
TheBigDirty27-Feb-11 16:50
memberTheBigDirty27-Feb-11 16:50 
GeneralRe: iocp socket server Pin
VF28-Feb-11 0:29
memberVF28-Feb-11 0:29 
QuestionHow to handle packet split? Pin
MarinDaniel26-Jun-10 0:51
memberMarinDaniel26-Jun-10 0:51 
AnswerRe: How to handle packet split? Pin
MarinDaniel27-Jun-10 1:09
memberMarinDaniel27-Jun-10 1:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.171114.1 | Last Updated 29 Sep 2010
Article Copyright 2008 by Marcos Hidalgo Nunes
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid