SocketAsyncEventArgs SocketAsyncEventArgs SocketAsyncEventArgs SocketAsyncEventArgs Class

定義

代表非同步 (Asynchronous) 通訊端作業。Represents an asynchronous socket operation.

public ref class SocketAsyncEventArgs : EventArgs, IDisposable
public class SocketAsyncEventArgs : EventArgs, IDisposable
type SocketAsyncEventArgs = class
    inherit EventArgs
    interface IDisposable
Public Class SocketAsyncEventArgs
Inherits EventArgs
Implements IDisposable
繼承
SocketAsyncEventArgsSocketAsyncEventArgsSocketAsyncEventArgsSocketAsyncEventArgs
實作

範例

下列程式碼範例會實作使用的通訊端伺服器的連線邏輯SocketAsyncEventArgs類別。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. 中的程式碼範例顯示此範例會使用 BufferManager 類別SetBuffer(Byte[], Int32, Int32)方法。The BufferManager class that is used by this example is displayed in the code example for the SetBuffer(Byte[], Int32, Int32) method. SocketAsyncEventArgsPool 類別,可在此範例中所示的程式碼範例SocketAsyncEventArgs建構函式。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.
class Server
{
    private int m_numConnections;   // the maximum number of connections the sample is designed to handle simultaneously 
    private int m_receiveBufferSize;// buffer size to use for each socket I/O operation 
    BufferManager m_bufferManager;  // represents a large reusable set of buffers for all socket operations
    const int opsToPreAlloc = 2;    // read, write (don't alloc buffer space for accepts)
    Socket listenSocket;            // the socket used to listen for incoming connection requests
    // pool of reusable SocketAsyncEventArgs objects for write, read and accept socket operations
    SocketAsyncEventArgsPool m_readWritePool;
    int m_totalBytesRead;           // counter of the total # bytes received by the server
    int m_numConnectedSockets;      // the total number of clients connected to the server 
    Semaphore m_maxNumberAcceptedClients;

    // 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 Server(int numConnections, int receiveBufferSize)
    {
        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); 
    }

    // 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 void Init()
    {
        // Allocates one large byte buffer which all I/O operations use a piece of.  This gaurds 
        // against memory fragmentation
        m_bufferManager.InitBuffer();

        // preallocate pool of SocketAsyncEventArgs objects
        SocketAsyncEventArgs readWriteEventArg;

        for (int i = 0; i < m_numConnections; i++)
        {
            //Pre-allocate a set of reusable SocketAsyncEventArgs
            readWriteEventArg = new SocketAsyncEventArgs();
            readWriteEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
            readWriteEventArg.UserToken = new AsyncUserToken();

            // assign a byte buffer from the buffer pool to the SocketAsyncEventArg object
            m_bufferManager.SetBuffer(readWriteEventArg);

            // add SocketAsyncEventArg to the pool
            m_readWritePool.Push(readWriteEventArg);
        }

    }

    // 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 void Start(IPEndPoint localEndPoint)
    {
        // create the socket which listens for incoming connections
        listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        listenSocket.Bind(localEndPoint);
        // start the server with a listen backlog of 100 connections
        listenSocket.Listen(100);
        
        // post accepts on the listening socket
        StartAccept(null);            

        //Console.WriteLine("{0} connected sockets with one outstanding receive posted to each....press any key", m_outstandingReadCount);
        Console.WriteLine("Press any key to terminate the server process....");
        Console.ReadKey();
    }


    // 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 void StartAccept(SocketAsyncEventArgs acceptEventArg)
    {
        if (acceptEventArg == null)
        {
            acceptEventArg = new SocketAsyncEventArgs();
            acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed);
        }
        else
        {
            // socket must be cleared since the context object is being reused
            acceptEventArg.AcceptSocket = null;
        }

        m_maxNumberAcceptedClients.WaitOne();
        bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg);
        if (!willRaiseEvent)
        {
            ProcessAccept(acceptEventArg);
        }
    }

    // This method is the callback method associated with Socket.AcceptAsync 
    // operations and is invoked when an accept operation is complete
    //
    void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)
    {
        ProcessAccept(e);
    }

    private void ProcessAccept(SocketAsyncEventArgs e)
    {
        Interlocked.Increment(ref m_numConnectedSockets);
        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
        SocketAsyncEventArgs readEventArgs = m_readWritePool.Pop();
        ((AsyncUserToken)readEventArgs.UserToken).Socket = e.AcceptSocket;

        // As soon as the client is connected, post a receive to the connection
        bool willRaiseEvent = e.AcceptSocket.ReceiveAsync(readEventArgs);
        if(!willRaiseEvent){
            ProcessReceive(readEventArgs);
        }

        // Accept the next connection request
        StartAccept(e);
    }

    // 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>
    void IO_Completed(object sender, SocketAsyncEventArgs e)
    {
        // determine which type of operation just completed and call the associated handler
        switch (e.LastOperation)
        {
            case SocketAsyncOperation.Receive:
                ProcessReceive(e);
                break;
            case SocketAsyncOperation.Send:
                ProcessSend(e);
                break;
            default:
                throw new ArgumentException("The last operation completed on the socket was not a receive or send");
        }       

    }
    
    // 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
        AsyncUserToken token = (AsyncUserToken)e.UserToken;
        if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
        {
            //increment the count of the total bytes receive by the server
            Interlocked.Add(ref 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);
            bool willRaiseEvent = token.Socket.SendAsync(e);
            if (!willRaiseEvent)
            {
                ProcessSend(e);
            }
          
        }
        else
        {
            CloseClientSocket(e);
        }
    }

    // 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 void ProcessSend(SocketAsyncEventArgs e)
    {
        if (e.SocketError == SocketError.Success)
        {
            // done echoing data back to the client
            AsyncUserToken token = (AsyncUserToken)e.UserToken;
            // read the next block of data send from the client
            bool willRaiseEvent = token.Socket.ReceiveAsync(e);
            if (!willRaiseEvent)
            {
                ProcessReceive(e);
            }
        }
        else
        {
            CloseClientSocket(e);
        }
    }

    private void CloseClientSocket(SocketAsyncEventArgs e)
    {
        AsyncUserToken token = e.UserToken as AsyncUserToken;

        // close the socket associated with the client
        try
        {
            token.Socket.Shutdown(SocketShutdown.Send);
        }
        // throws if client process has already closed
        catch (Exception) { }
        token.Socket.Close();

        // decrement the counter keeping track of the total number of clients connected to the server
        Interlocked.Decrement(ref m_numConnectedSockets);
        
        // Free the SocketAsyncEventArg so they can be reused by another client
        m_readWritePool.Push(e);
        
        m_maxNumberAcceptedClients.Release();
        Console.WriteLine("A client has been disconnected from the server. There are {0} clients connected to the server", m_numConnectedSockets);
    }

}    

備註

SocketAsyncEventArgs類別是一組增強功能的一部分System.Net.Sockets.Socket提供可供專業化的高效能通訊端應用程式的另一種非同步模式的類別。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).

這些增強功能的主要功能是在大量的非同步通訊端 I/O 期間,避免重複配置和同步處理物件。The main feature of these enhancements is the avoidance of the repeated allocation and synchronization of objects during high-volume asynchronous socket I/O. 目前實作的 Begin/End 設計模式System.Net.Sockets.Socket類別會要求System.IAsyncResult物件可配置給每個非同步通訊端作業。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.

在新System.Net.Sockets.Socket類別增強功能,作業會描述可重複使用的非同步通訊端SocketAsyncEventArgs物件配置和維護應用程式。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. 應用程式可以視需要建立許多 SocketAsyncEventArgs 物件。The application can create as many of the SocketAsyncEventArgs objects that it needs. 例如,如果伺服器應用程式需要有 15 個通訊端接受作業未完成任何時候以支援內送的用戶端連線比率,它可以配置 15 個可重複使用SocketAsyncEventArgs針對該用途的物件。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. 配置新 SocketAsyncEventArgs 內容物件,或從應用程式集區取得一個可用的內容物件。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. 呼叫適當的通訊端方法 (xxxAsync) 來啟始非同步作業。Call the appropriate socket method (xxxAsync) to initiate the asynchronous operation.

  4. 如果非同步通訊端方法 (xxxAsync) 傳回 true,在回呼中,查詢完成狀態的內容的屬性。If the asynchronous socket method (xxxAsync) returns true, in the callback, query the context properties for completion status.

  5. 如果非同步通訊端方法 (xxxAsync) 會傳回 false,以同步方式完成此作業。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.

新的非同步通訊端作業內容物件的存留期取決於所參考的應用程式程式碼和非同步 I/O 參考。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.

建構函式

SocketAsyncEventArgs() SocketAsyncEventArgs() SocketAsyncEventArgs() SocketAsyncEventArgs()

建立空的 SocketAsyncEventArgs 執行個體。Creates an empty SocketAsyncEventArgs instance.

屬性

AcceptSocket AcceptSocket AcceptSocket AcceptSocket

取得或設定要使用的通訊端,或是已建立並且使用非同步通訊端方法接受連線的通訊端。Gets or sets the socket to use or the socket created for accepting a connection with an asynchronous socket method.

Buffer Buffer Buffer Buffer

取得要和非同步通訊端方法一起使用的資料緩衝區。Gets the data buffer to use with an asynchronous socket method.

BufferList BufferList BufferList BufferList

取得或設定要和非同步通訊端方法一起使用的資料緩衝區之陣列。Gets or sets an array of data buffers to use with an asynchronous socket method.

BytesTransferred BytesTransferred BytesTransferred BytesTransferred

取得通訊端作業中所傳輸的位元組數目。Gets the number of bytes transferred in the socket operation.

ConnectByNameError ConnectByNameError ConnectByNameError ConnectByNameError

取得使用 DnsEndPoint 時發生連接失敗的例外狀況 (Exception)。Gets the exception in the case of a connection failure when a DnsEndPoint was used.

ConnectSocket ConnectSocket ConnectSocket ConnectSocket

Socket 方法成功完成後已建立和連接的 ConnectAsync 物件。The created and connected Socket object after successful completion of the ConnectAsync method.

Count Count Count Count

取得非同步作業中要傳送或接收的資料量上限 (以位元組為單位)。Gets the maximum amount of data, in bytes, to send or receive in an asynchronous operation.

DisconnectReuseSocket DisconnectReuseSocket DisconnectReuseSocket DisconnectReuseSocket

取得或設定值,指定在中斷連接作業後是否可以重複使用通訊端。Gets or sets a value that specifies if socket can be reused after a disconnect operation.

LastOperation LastOperation LastOperation LastOperation

取得最近使用這個內容物件執行的通訊端作業類型。Gets the type of socket operation most recently performed with this context object.

MemoryBuffer MemoryBuffer MemoryBuffer MemoryBuffer
Offset Offset Offset Offset

取得 Buffer 屬性所參考之資料緩衝區中的位移 (以位元組為單位)。Gets the offset, in bytes, into the data buffer referenced by the Buffer property.

ReceiveMessageFromPacketInfo ReceiveMessageFromPacketInfo ReceiveMessageFromPacketInfo ReceiveMessageFromPacketInfo

取得接收之封包的 IP 位址和介面。Gets the IP address and interface of a received packet.

RemoteEndPoint RemoteEndPoint RemoteEndPoint RemoteEndPoint

取得或設定非同步作業的遠端 IP 端點。Gets or sets the remote IP endpoint for an asynchronous operation.

SendPacketsElements SendPacketsElements SendPacketsElements SendPacketsElements

取得或設定要為 SendPacketsAsync(SocketAsyncEventArgs) 方法所使用的非同步作業傳送的緩衝區陣列。Gets or sets an array of buffers to be sent for an asynchronous operation used by the SendPacketsAsync(SocketAsyncEventArgs) method.

SendPacketsFlags SendPacketsFlags SendPacketsFlags SendPacketsFlags

取得或設定 TransmitFileOptions 方法所使用之非同步作業的 SendPacketsAsync(SocketAsyncEventArgs) 值的位元組合。Gets or sets a bitwise combination of TransmitFileOptions values for an asynchronous operation used by the SendPacketsAsync(SocketAsyncEventArgs) method.

SendPacketsSendSize SendPacketsSendSize SendPacketsSendSize SendPacketsSendSize

取得或設定傳送作業中所使用的資料區塊大小 (以位元組為單位)。Gets or sets the size, in bytes, of the data block used in the send operation.

SocketClientAccessPolicyProtocol SocketClientAccessPolicyProtocol SocketClientAccessPolicyProtocol SocketClientAccessPolicyProtocol

取得或設定要用來下載通訊端用戶端存取原則檔的通訊協定。Gets or sets the protocol to use to download the socket client access policy file.

SocketError SocketError SocketError SocketError

取得或設定非同步通訊端作業的結果。Gets or sets the result of the asynchronous socket operation.

SocketFlags SocketFlags SocketFlags SocketFlags

取得非同步通訊端作業的結果,或設定非同步作業的行為。Gets the results of an asynchronous socket operation or sets the behavior of an asynchronous operation.

UserToken UserToken UserToken UserToken

取得或設定與這個非同步通訊端作業相關聯的使用者或應用程式物件。Gets or sets a user or application object associated with this asynchronous socket operation.

方法

Dispose() Dispose() Dispose() Dispose()

釋放 SocketAsyncEventArgs 執行個體所使用的 Unmanaged 資源,並選擇性地處置 Managed 資源。Releases the unmanaged resources used by the SocketAsyncEventArgs instance and optionally disposes of the managed resources.

Equals(Object) Equals(Object) Equals(Object) Equals(Object)

判斷指定的物件是否等於目前的物件。Determines whether the specified object is equal to the current object.

(Inherited from Object)
Finalize() Finalize() Finalize() Finalize()

釋放 SocketAsyncEventArgs 類別所使用的資源。Frees resources used by the SocketAsyncEventArgs class.

GetHashCode() GetHashCode() GetHashCode() GetHashCode()

做為預設雜湊函式。Serves as the default hash function.

(Inherited from Object)
GetType() GetType() GetType() GetType()

取得目前執行個體的 TypeGets the Type of the current instance.

(Inherited from Object)
MemberwiseClone() MemberwiseClone() MemberwiseClone() MemberwiseClone()

建立目前 Object 的淺層複本 (Shallow Copy)。Creates a shallow copy of the current Object.

(Inherited from Object)
OnCompleted(SocketAsyncEventArgs) OnCompleted(SocketAsyncEventArgs) OnCompleted(SocketAsyncEventArgs) OnCompleted(SocketAsyncEventArgs)

代表在非同步作業完成時所呼叫的方法。Represents a method that is called when an asynchronous operation completes.

SetBuffer(Byte[], Int32, Int32) SetBuffer(Byte[], Int32, Int32) SetBuffer(Byte[], Int32, Int32) SetBuffer(Byte[], Int32, Int32)

設定要和非同步通訊端方法一起使用的資料緩衝區。Sets the data buffer to use with an asynchronous socket method.

SetBuffer(Int32, Int32) SetBuffer(Int32, Int32) SetBuffer(Int32, Int32) SetBuffer(Int32, Int32)

設定要和非同步通訊端方法一起使用的資料緩衝區。Sets the data buffer to use with an asynchronous socket method.

SetBuffer(Memory<Byte>) SetBuffer(Memory<Byte>) SetBuffer(Memory<Byte>) SetBuffer(Memory<Byte>)
ToString() ToString() ToString() ToString()

傳回代表目前物件的字串。Returns a string that represents the current object.

(Inherited from Object)

事件

Completed Completed Completed Completed

用來完成非同步作業的事件。The event used to complete an asynchronous operation.

適用於

另請參閱