SocketAsyncEventArgs Classe
Definizione
Importante
Alcune informazioni sono relative alla release non definitiva del prodotto, che potrebbe subire modifiche significative prima della release definitiva. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Rappresenta un'operazione socket asincrona.
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
- Ereditarietà
- Implementazioni
Esempio
Nell'esempio di codice seguente viene implementata la logica di connessione per il server socket che usa la SocketAsyncEventArgs classe . Dopo aver accettato una connessione, tutti i dati letti dal client vengono inviati al client. La lettura e l'eco al modello client continuano fino a quando il client non si disconnette. La classe BufferManager utilizzata da questo esempio viene visualizzata nell'esempio di codice per il SetBuffer(Byte[], Int32, Int32) metodo . La classe SocketAsyncEventArgsPool utilizzata in questo esempio viene visualizzata nell'esempio di codice per il SocketAsyncEventArgs costruttore.
// 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);
// 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
SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs();
acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed);
StartAccept(acceptEventArg);
//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)
{
// loop while the method completes synchronously
bool willRaiseEvent = false;
while (!willRaiseEvent)
{
m_maxNumberAcceptedClients.WaitOne();
// socket must be cleared since the context object is being reused
acceptEventArg.AcceptSocket = null;
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);
// Accept the next connection request
StartAccept(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();
readEventArgs.UserToken = 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);
}
}
// 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
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);
Socket socket = (Socket)e.UserToken;
bool willRaiseEvent = 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
Socket socket = (Socket)e.UserToken;
// read the next block of data send from the client
bool willRaiseEvent = socket.ReceiveAsync(e);
if (!willRaiseEvent)
{
ProcessReceive(e);
}
}
else
{
CloseClientSocket(e);
}
}
private void CloseClientSocket(SocketAsyncEventArgs e)
{
Socket socket = (Socket)e.UserToken;
// close the socket associated with the client
try
{
socket.Shutdown(SocketShutdown.Send);
}
// throws if client process has already closed
catch (Exception) { }
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);
}
}
Commenti
La SocketAsyncEventArgs classe fa parte di un set di miglioramenti alla System.Net.Sockets.Socket classe che forniscono un modello asincrono alternativo che può essere usato da applicazioni socket ad alte prestazioni specializzate. Questa classe è stata progettata specificamente per le applicazioni server di rete che richiedono prestazioni elevate. Un'applicazione può usare il modello asincrono avanzato esclusivamente o solo nelle aree ad accesso frequente di destinazione( ad esempio, quando si ricevono grandi quantità di dati).
La caratteristica principale di questi miglioramenti è l'evitare l'allocazione ripetuta e la sincronizzazione degli oggetti durante l'I/O asincrona del socket ad alto volume. Il modello di progettazione Begin/End attualmente implementato dalla classe richiede l'allocazione System.Net.Sockets.Socket di un System.IAsyncResult oggetto per ogni operazione socket asincrona.
Nei nuovi System.Net.Sockets.Socket miglioramenti della classe, le operazioni socket asincrone sono descritte da oggetti riutilizzabili SocketAsyncEventArgs allocati e gestiti dall'applicazione. Le applicazioni socket ad alte prestazioni conoscono meglio la quantità di operazioni socket sovrapposte che devono essere sostenute. L'applicazione può creare il numero di SocketAsyncEventArgs oggetti necessari. Ad esempio, se un'applicazione server deve avere 15 operazioni di accettazione socket in sospeso in qualsiasi momento per supportare le frequenze di connessione client in ingresso, può allocare 15 oggetti riutilizzabili SocketAsyncEventArgs a tale scopo.
Il modello per eseguire un'operazione socket asincrona con questa classe è costituito dai passaggi seguenti:
Allocare un nuovo SocketAsyncEventArgs oggetto contesto o ottenere uno gratuito da un pool di applicazioni.
Impostare le proprietà sull'oggetto contesto sull'operazione da eseguire (il metodo di callback di completamento, il buffer di dati, l'offset nel buffer e la quantità massima di dati da trasferire, ad esempio).
Chiamare il metodo socket appropriato (xxxAsync) per avviare l'operazione asincrona.
Se il metodo socket asincrono (xxxAsync) restituisce true, nel callback eseguire una query sulle proprietà del contesto per lo stato di completamento.
Se il metodo socket asincrono (xxxAsync) restituisce false, l'operazione è stata completata in modo sincrono. È possibile eseguire una query sulle proprietà del contesto per il risultato dell'operazione.
Riutilizzare il contesto per un'altra operazione, inserirlo di nuovo nel pool o rimuoverlo.
La durata del nuovo oggetto contesto dell'operazione socket asincrona è determinata dai riferimenti dal codice dell'applicazione e dai riferimenti di I/O asincroni. Non è necessario che l'applicazione mantenga un riferimento a un oggetto contesto dell'operazione socket asincrona dopo l'invio come parametro a uno dei metodi di operazione socket asincrona. Verrà fatto riferimento fino a quando non viene restituito il callback di completamento. Tuttavia, è vantaggioso per l'applicazione conservare il riferimento al contesto in modo che possa essere riutilizzato per una futura operazione socket asincrona.
Costruttori
| Nome | Descrizione |
|---|---|
| SocketAsyncEventArgs() |
Crea un'istanza vuota SocketAsyncEventArgs . |
Proprietà
| Nome | Descrizione |
|---|---|
| AcceptSocket |
Ottiene o imposta il socket da utilizzare o il socket creato per accettare una connessione con un metodo socket asincrono. |
| Buffer |
Ottiene il buffer di dati da utilizzare con un metodo socket asincrono. |
| BufferList |
Ottiene o imposta una matrice di buffer di dati da utilizzare con un metodo socket asincrono. |
| BytesTransferred |
Ottiene il numero di byte trasferiti nell'operazione socket. |
| ConnectByNameError |
Ottiene l'eccezione nel caso di un errore di connessione quando è stato utilizzato un oggetto DnsEndPoint . |
| ConnectSocket |
Oggetto creato e connesso Socket dopo il completamento corretto del ConnectAsync metodo. |
| Count |
Ottiene la quantità massima di dati, in byte, da inviare o ricevere in un'operazione asincrona. |
| DisconnectReuseSocket |
Ottiene o imposta un valore che specifica se il socket può essere riutilizzato dopo un'operazione di disconnessione. |
| LastOperation |
Ottiene il tipo di operazione socket eseguita più di recente con questo oggetto contesto. |
| MemoryBuffer |
Ottiene l'area di memoria da utilizzare come buffer con un metodo socket asincrono. |
| Offset |
Ottiene l'offset, in byte, nel buffer di dati a cui fa riferimento la Buffer proprietà . |
| ReceiveMessageFromPacketInfo |
Ottiene l'indirizzo IP e l'interfaccia di un pacchetto ricevuto. |
| RemoteEndPoint |
Ottiene o imposta l'endpoint IP remoto per un'operazione asincrona. |
| SendPacketsElements |
Ottiene o imposta una matrice di buffer da inviare per un'operazione asincrona utilizzata dal SendPacketsAsync(SocketAsyncEventArgs) metodo . |
| SendPacketsFlags |
Ottiene o imposta una combinazione bit per bit di TransmitFileOptions valori per un'operazione asincrona utilizzata dal SendPacketsAsync(SocketAsyncEventArgs) metodo . |
| SendPacketsSendSize |
Ottiene o imposta le dimensioni, in byte, del blocco di dati utilizzato nell'operazione di invio. |
| SocketClientAccessPolicyProtocol |
Obsoleti.
Ottiene o imposta il protocollo da utilizzare per scaricare il file dei criteri di accesso client socket. |
| SocketError |
Ottiene o imposta il risultato dell'operazione socket asincrona. |
| SocketFlags |
Ottiene i risultati di un'operazione socket asincrona o imposta il comportamento di un'operazione asincrona. |
| UserToken |
Ottiene o imposta un oggetto utente o applicazione associato a questa operazione socket asincrona. |
Metodi
| Nome | Descrizione |
|---|---|
| Dispose() |
Rilascia le risorse non gestite usate dall'istanza SocketAsyncEventArgs e, facoltativamente, elimina le risorse gestite. |
| Equals(Object) |
Determina se l'oggetto specificato è uguale all'oggetto corrente. (Ereditato da Object) |
| Finalize() |
Libera le risorse usate dalla SocketAsyncEventArgs classe . |
| GetHashCode() |
Funge da funzione hash predefinita. (Ereditato da Object) |
| GetType() |
Ottiene il Type dell'istanza corrente. (Ereditato da Object) |
| MemberwiseClone() |
Crea una copia superficiale del Objectcorrente. (Ereditato da Object) |
| OnCompleted(SocketAsyncEventArgs) |
Rappresenta un metodo chiamato al completamento di un'operazione asincrona. |
| SetBuffer(Byte[], Int32, Int32) |
Imposta il buffer di dati da utilizzare con un metodo socket asincrono. |
| SetBuffer(Int32, Int32) |
Imposta il buffer di dati da utilizzare con un metodo socket asincrono. |
| SetBuffer(Memory<Byte>) |
Imposta l'area di memoria da utilizzare come buffer con un metodo socket asincrono. |
| ToString() |
Restituisce una stringa che rappresenta l'oggetto corrente. (Ereditato da Object) |
Eventi
| Nome | Descrizione |
|---|---|
| Completed |
Evento utilizzato per completare un'operazione asincrona. |
Si applica a
Vedi anche
- IAsyncResult
- Socket
- AcceptAsync(SocketAsyncEventArgs)
- ConnectAsync(SocketAsyncEventArgs)
- DisconnectAsync(SocketAsyncEventArgs)
- ReceiveAsync(SocketAsyncEventArgs)
- ReceiveFromAsync(SocketAsyncEventArgs)
- ReceiveMessageFromAsync(SocketAsyncEventArgs)
- SendAsync(SocketAsyncEventArgs)
- SendPacketsAsync(SocketAsyncEventArgs)
- SendToAsync(SocketAsyncEventArgs)
- programmazione di rete in .NET Framework
- Traccia di rete in .NET Framework
- Miglioramenti delle prestazioni socket nella versione 3.5