SocketAsyncEventArgs SocketAsyncEventArgs SocketAsyncEventArgs SocketAsyncEventArgs Class

定义

表示异步套接字操作。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);
    }

}    

注解

类是System.Net.Sockets.Socket类的一组增强功能的一部分, 这些增强功能提供了一种可供专用高性能套接字应用程序使用的替代异步模式。 SocketAsyncEventArgsThe 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. 当前由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个套接字接受操作来支持传入的客户端连接速率, 则它可以SocketAsyncEventArgs分配15个可重复使用的对象来实现此目的。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 时,在出现连接故障的情况下获取异常。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 实例使用的非托管资源,并可选择释放托管资源。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 的浅表副本。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.

适用于

另请参阅