This documentation is archived and is not being maintained.

SocketAsyncEventArgs Class

Represents an asynchronous socket operation.


Namespace:  System.Net.Sockets
Assembly:  System (in System.dll)

Public Class SocketAsyncEventArgs _
	Inherits EventArgs _
	Implements IDisposable

The SocketAsyncEventArgs type exposes the following members.

Public methodSocketAsyncEventArgsCreates an empty SocketAsyncEventArgs instance.

Public propertyAcceptSocketGets or sets the socket to use or the socket created for accepting a connection with an asynchronous socket method.
Public propertyBufferGets the data buffer to use with an asynchronous socket method.
Public propertyBufferListGets or sets an array of data buffers to use with an asynchronous socket method.
Public propertyBytesTransferredGets the number of bytes transferred in the socket operation.
Public propertyConnectByNameErrorGets the exception in the case of a connection failure when a DnsEndPoint was used.
Public propertyConnectSocketThe created and connected Socket object after successful completion of the ConnectAsync method.
Public propertyCountGets the maximum amount of data, in bytes, to send or receive in an asynchronous operation.
Public propertyDisconnectReuseSocketGets or sets a value that specifies if socket can be reused after a disconnect operation.
Public propertyLastOperationGets the type of socket operation most recently performed with this context object.
Public propertyOffsetGets the offset, in bytes, into the data buffer referenced by the Buffer property.
Public propertyReceiveMessageFromPacketInfoGets the IP address and interface of a received packet.
Public propertyRemoteEndPointGets or sets the remote IP endpoint for an asynchronous operation.
Public propertySendPacketsElementsGets or sets an array of buffers to be sent for an asynchronous operation used by the Socket.SendPacketsAsync method.
Public propertySendPacketsFlagsGets or sets a bitwise combination of TransmitFileOptions values for an asynchronous operation used by the Socket.SendPacketsAsync method.
Public propertySendPacketsSendSizeGets or sets the size, in bytes, of the data block used in the send operation.
Public propertySocketErrorGets or sets the result of the asynchronous socket operation.
Public propertySocketFlagsGets the results of an asynchronous socket operation or sets the behavior of an asynchronous operation.
Public propertyUserTokenGets or sets a user or application object associated with this asynchronous socket operation.

Public methodDisposeReleases the unmanaged resources used by the SocketAsyncEventArgs instance and optionally disposes of the managed resources.
Public methodEquals(Object)Determines whether the specified Object is equal to the current Object. (Inherited from Object.)
Protected methodFinalizeFrees resources used by the SocketAsyncEventArgs class. (Overrides Object.Finalize.)
Public methodGetHashCodeServes as a hash function for a particular type. (Inherited from Object.)
Public methodGetTypeGets the Type of the current instance. (Inherited from Object.)
Protected methodMemberwiseCloneCreates a shallow copy of the current Object. (Inherited from Object.)
Protected methodOnCompletedRepresents a method that is called when an asynchronous operation completes.
Public methodSetBuffer(Int32, Int32)Sets the data buffer to use with an asynchronous socket method.
Public methodSetBuffer(Byte(), Int32, Int32)Sets the data buffer to use with an asynchronous socket method.
Public methodToStringReturns a string that represents the current object. (Inherited from Object.)

Public eventCompletedThe event used to complete an asynchronous operation.

The SocketAsyncEventArgs class is part of a set of enhancements to the System.Net.Sockets.Socket class that provide an alternative asynchronous pattern that can be used by specialized high-performance socket applications. This class was specifically designed for network server applications that require high performance. An application can use the enhanced asynchronous pattern exclusively or only in targeted hot areas (for example, when receiving large amounts of data).

The main feature of these enhancements is the avoidance of the repeated allocation and synchronization of objects during high-volume asynchronous socket I/O. The Begin/End design pattern currently implemented by the System.Net.Sockets.Socket class requires a System.IAsyncResult object be allocated for each asynchronous socket operation.

In the new System.Net.Sockets.Socket class enhancements, asynchronous socket operations are described by reusable SocketAsyncEventArgs objects allocated and maintained by the application. High-performance socket applications know best the amount of overlapped socket operations that must be sustained. The application can create as many of the SocketAsyncEventArgs objects that it needs. For example, if a server application needs to have 15 socket accept operations outstanding at all times to support incoming client connection rates, it can allocate 15 reusable SocketAsyncEventArgs objects for that purpose.

The pattern for performing an asynchronous socket operation with this class consists of the following steps:

  1. Allocate a new SocketAsyncEventArgs context object, or get a free one from an application pool.

  2. Set properties on the context object to the operation about to be performed (the completion callback method, the data buffer, the offset into the buffer, and the maximum amount of data to transfer, for example).

  3. Call the appropriate socket method (xxxAsync) to initiate the asynchronous operation.

  4. If the asynchronous socket method (xxxAsync) returns true, in the callback, query the context properties for completion status.

  5. If the asynchronous socket method (xxxAsync) returns false, the operation completed synchronously. The context properties may be queried for the operation result.

  6. Reuse the context for another operation, put it back in the pool, or discard it.

The lifetime of the new asynchronous socket operation context object is determined by references by the application code and asynchronous I/O references. It is not necessary for the application to retain a reference to an asynchronous socket operation context object after it is submitted as a parameter to one of the asynchronous socket operation methods. It will remain referenced until the completion callback returns. However it is advantageous for the application to retain the reference to the context so that it can be reused for a future asynchronous socket operation.

The following code example implements the connection logic for the socket server that uses the SocketAsyncEventArgs class. After accepting a connection, all data read from the client is sent back to the client. The read and echo back to the client pattern is continued until the client disconnects. The BufferManager class that is used by this example is displayed in the code example for the SetBuffer(Byte(), Int32, Int32) method. The SocketAsyncEventArgsPool class that is used in this example is displayed in the code example for the SocketAsyncEventArgs constructor.

' Implements the connection logic for the socket server.  
' After accepting a connection, all data read from the client 
' is sent back to the client. The read and echo back to the client pattern 
' is continued until the client disconnects.
Friend Class Server
    Private m_numConnections As Integer ' the maximum number of connections the sample is designed to handle simultaneously
    Private m_receiveBufferSize As Integer ' buffer size to use for each socket I/O operation
    Private m_bufferManager As BufferManager ' represents a large reusable set of buffers for all socket operations
    Private Const opsToPreAlloc As Integer = 2 ' read, write (don't alloc buffer space for accepts)
    Private listenSocket As Socket ' the socket used to listen for incoming connection requests
    ' pool of reusable SocketAsyncEventArgs objects for write, read and accept socket operations
    Private m_readWritePool As SocketAsyncEventArgsPool
    Private m_totalBytesRead As Integer ' counter of the total # bytes received by the server
    Private m_numConnectedSockets As Integer ' the total number of clients connected to the server
    Private m_maxNumberAcceptedClients As Semaphore

    ' Create an uninitialized server instance.  
    ' To start the server listening for connection requests
    ' call the Init method followed by Start method 
    ' <param name="numConnections">the maximum number of connections the sample is designed to handle simultaneously</param>
    ' <param name="receiveBufferSize">buffer size to use for each socket I/O operation</param>
    Public Sub New(ByVal numConnections As Integer, ByVal receiveBufferSize As Integer)
        m_totalBytesRead = 0
        m_numConnectedSockets = 0
        m_numConnections = numConnections
        m_receiveBufferSize = receiveBufferSize
        ' allocate buffers such that the maximum number of sockets can have one outstanding read and 
        'write posted to the socket simultaneously  
        m_bufferManager = New BufferManager(receiveBufferSize * numConnections * opsToPreAlloc, receiveBufferSize)

        m_readWritePool = New SocketAsyncEventArgsPool(numConnections)
        m_maxNumberAcceptedClients = New Semaphore(numConnections, numConnections)
    End Sub

    ' Initializes the server by preallocating reusable buffers and 
    ' context objects.  These objects do not need to be preallocated 
    ' or reused, but it is done this way to illustrate how the API can 
    ' easily be used to create reusable objects to increase server performance.
    Public Sub Init()
        ' Allocates one large byte buffer which all I/O operations use a piece of.  This gaurds 
        ' against memory fragmentation

        ' preallocate pool of SocketAsyncEventArgs objects
        Dim readWriteEventArg As SocketAsyncEventArgs

        For i = 0 To m_numConnections - 1
            'Pre-allocate a set of reusable SocketAsyncEventArgs
            readWriteEventArg = New SocketAsyncEventArgs()
            AddHandler readWriteEventArg.Completed, AddressOf IO_Completed
            readWriteEventArg.UserToken = New AsyncUserToken()

            ' assign a byte buffer from the buffer pool to the SocketAsyncEventArg object

            ' add SocketAsyncEventArg to the pool
        Next i

    End Sub

    ' Starts the server such that it is listening for 
    ' incoming connection requests.    
    ' <param name="localEndPoint">The endpoint which the server will listening 
    ' for connection requests on</param>
    Public Sub Start(ByVal localEndPoint As IPEndPoint)
        ' create the socket which listens for incoming connections
        listenSocket = New Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
        ' start the server with a listen backlog of 100 connections

        ' post accepts on the listening socket

        'Console.WriteLine("{0} connected sockets with one outstanding receive posted to any key", m_outstandingReadCount)
        Console.WriteLine("Press any key to terminate the server process....")
    End Sub

    ' Begins an operation to accept a connection request from the client 
    ' <param name="acceptEventArg">The context object to use when issuing 
    ' the accept operation on the server's listening socket</param>
    Public Sub StartAccept(ByVal acceptEventArg As SocketAsyncEventArgs)
        If acceptEventArg Is Nothing Then
            acceptEventArg = New SocketAsyncEventArgs()
            AddHandler acceptEventArg.Completed, AddressOf AcceptEventArg_Completed
            ' socket must be cleared since the context object is being reused
            acceptEventArg.AcceptSocket = Nothing
        End If

        Dim willRaiseEvent As Boolean = listenSocket.AcceptAsync(acceptEventArg)
        If Not willRaiseEvent Then
        End If
    End Sub

    ' This method is the callback method associated with Socket.AcceptAsync 
    ' operations and is invoked when an accept operation is complete
    Private Sub AcceptEventArg_Completed(ByVal sender As Object, ByVal e As SocketAsyncEventArgs)
    End Sub

    Private Sub ProcessAccept(ByVal e As SocketAsyncEventArgs)
        Console.WriteLine("Client connection accepted. There are {0} clients connected to the server", m_numConnectedSockets)

        ' Get the socket for the accepted client connection and put it into the 
        'ReadEventArg object user token
        Dim readEventArgs As SocketAsyncEventArgs = m_readWritePool.Pop()
        CType(readEventArgs.UserToken, AsyncUserToken).Socket = e.AcceptSocket

        ' As soon as the client is connected, post a receive to the connection
        Dim willRaiseEvent As Boolean = e.AcceptSocket.ReceiveAsync(readEventArgs)
        If Not willRaiseEvent Then
        End If

        ' Accept the next connection request
    End Sub

    ' This method is called whenever a receive or send operation is completed on a socket 
    ' <param name="e">SocketAsyncEventArg associated with the completed receive operation</param>
    Private Sub IO_Completed(ByVal sender As Object, ByVal e As SocketAsyncEventArgs)
        ' determine which type of operation just completed and call the associated handler
        Select Case e.LastOperation
            Case SocketAsyncOperation.Receive
            Case SocketAsyncOperation.Send
            Case Else
                Throw New ArgumentException("The last operation completed on the socket was not a receive or send")
        End Select

    End Sub

    ' 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 Sub ProcessReceive(ByVal e As SocketAsyncEventArgs)
        ' check if the remote host closed the connection
        Dim token As AsyncUserToken = CType(e.UserToken, AsyncUserToken)
        If e.BytesTransferred > 0 AndAlso e.SocketError = SocketError.Success Then
            'increment the count of the total bytes receive by the server
            Interlocked.Add(m_totalBytesRead, e.BytesTransferred)
            Console.WriteLine("The server has read a total of {0} bytes", m_totalBytesRead)

            'echo the data received back to the client
            e.SetBuffer(e.Offset, e.BytesTransferred)
            Dim willRaiseEvent As Boolean = token.Socket.SendAsync(e)
            If Not willRaiseEvent Then
            End If

        End If
    End Sub

    ' 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
    ' <param name="e"></param>
    Private Sub ProcessSend(ByVal e As SocketAsyncEventArgs)
        If e.SocketError = SocketError.Success Then
            ' done echoing data back to the client
            Dim token As AsyncUserToken = CType(e.UserToken, AsyncUserToken)
            ' read the next block of data send from the client
            Dim willRaiseEvent As Boolean = token.Socket.ReceiveAsync(e)
            If Not willRaiseEvent Then
            End If
        End If
    End Sub

    Private Sub CloseClientSocket(ByVal e As SocketAsyncEventArgs)
        Dim token As AsyncUserToken = TryCast(e.UserToken, AsyncUserToken)

        ' close the socket associated with the client
            ' throws if client process has already closed
        Catch e1 As Exception
        End Try

        ' decrement the counter keeping track of the total number of clients connected to the server
        Console.WriteLine("A client has been disconnected from the server. There are {0} clients connected to the server", m_numConnectedSockets)

        ' Free the SocketAsyncEventArg so they can be reused by another client
    End Sub

End Class

.NET Framework

Supported in: 4, 3.5 SP1, 3.0 SP1, 2.0 SP1

.NET Framework Client Profile

Supported in: 4, 3.5 SP1

Windows 7, Windows Vista SP1 or later, Windows XP SP3, Windows Server 2008 (Server Core not supported), Windows Server 2008 R2 (Server Core supported with SP1 or later), Windows Server 2003 SP2

The .NET Framework does not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.