SocketAsyncEventArgs Classe
Definição
Importante
Algumas informações se referem a produtos de pré-lançamento que podem ser substancialmente modificados antes do lançamento. A Microsoft não oferece garantias, expressas ou implícitas, das informações aqui fornecidas.
Representa uma operação de soquete assíncrono.
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
- Herança
- Implementações
Exemplos
O exemplo de código a seguir implementa a lógica de conexão para o servidor de soquete que usa a SocketAsyncEventArgs classe . Depois de aceitar uma conexão, todos os dados lidos do cliente são enviados de volta para o cliente. A leitura e o eco de volta para o padrão do cliente são continuados até que o cliente se desconecte. A classe BufferManager usada por este exemplo é exibida no exemplo de código para o SetBuffer(Byte[], Int32, Int32) método . A classe SocketAsyncEventArgsPool usada neste exemplo é exibida no exemplo de código para o SocketAsyncEventArgs construtor.
// 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);
}
}
Comentários
A SocketAsyncEventArgs classe faz parte de um conjunto de aprimoramentos para a System.Net.Sockets.Socket classe que fornecem um padrão assíncrono alternativo que pode ser usado por aplicativos de soquete especializados de alto desempenho. Essa classe foi projetada especificamente para aplicativos de servidor de rede que exigem alto desempenho. Um aplicativo pode usar o padrão assíncrono aprimorado exclusivamente ou somente em áreas quentes de destino (por exemplo, ao receber grandes quantidades de dados).
O principal recurso dessas melhorias é evitar a alocação e a sincronização repetidas de objetos durante a E/S de soquete assíncrono de alto volume. O padrão de design Begin/End atualmente implementado pela System.Net.Sockets.Socket classe requer que um System.IAsyncResult objeto seja alocado para cada operação de soquete assíncrona.
Nos novos System.Net.Sockets.Socket aprimoramentos de classe, as operações de soquete assíncronas são descritas por objetos reutilizáveis SocketAsyncEventArgs alocados e mantidos pelo aplicativo. Os aplicativos de soquete de alto desempenho sabem muito bem a quantidade de operações de soquete sobreposto que devem ser sustentadas. O aplicativo pode criar a quantidade de objetos SocketAsyncEventArgs de que precisar. Por exemplo, se um aplicativo de servidor precisar ter 15 operações de aceitação de soquete pendentes o tempo todo para dar suporte a taxas de conexão de cliente de entrada, ele poderá alocar 15 objetos reutilizáveis SocketAsyncEventArgs para essa finalidade.
O padrão para executar uma operação de soquete assíncrono com essa classe consiste nas seguintes etapas:
Alocar um novo objeto de contexto SocketAsyncEventArgs ou obter um gratuito em um pool de aplicativos.
Defina propriedades no objeto de contexto para a operação prestes a ser executada (o método de retorno de chamada de conclusão, o buffer de dados, o deslocamento para o buffer e a quantidade máxima de dados a serem transferidos, por exemplo).
Chamar o método de soquete apropriado (xxxAsync) para iniciar a operação assíncrona.
Se o método de soquete assíncrono (xxxAsync) retornar true, no retorno de chamada, consulte as propriedades de contexto para conclusão status.
Se o método de soquete assíncrono (xxxAsync) retornar false, a operação será concluída de forma síncrona. As propriedades do contexto podem ser consultadas para obter o resultado da operação.
Reutilizar o contexto para outra operação, colocá-lo novamente no pool ou descartá-lo.
O tempo de vida do novo objeto de contexto de operação de soquete assíncrono é determinado por referências pelo código do aplicativo e por referências assíncronas de E/S. Não é necessário que o aplicativo retenha uma referência a um objeto de contexto da operação de soquete assíncrono depois que ele é enviado como um parâmetro para um dos métodos da operação de soquete assíncrono. Ele permanecerá referenciado até o retorno do retorno de chamada de conclusão. No entanto, é vantajoso para o aplicativo manter a referência ao contexto para que ele possa ser reutilizado para uma operação de soquete assíncrona futura.
Construtores
SocketAsyncEventArgs() |
Cria uma instância SocketAsyncEventArgs vazia. |
SocketAsyncEventArgs(Boolean) |
Inicializa o SocketAsyncEventArgs. |
Propriedades
AcceptSocket |
Obtém ou define o soquete a ser usado ou o soquete criado para aceitar uma conexão com um método de soquete assíncrono. |
Buffer |
Obtém o buffer de dados a ser usado com um método de soquete assíncrono. |
BufferList |
Obtém ou define uma matriz de buffers de dados a ser usada com um método de soquete assíncrono. |
BytesTransferred |
Obtém o número de bytes transferidos na operação de soquete. |
ConnectByNameError |
Obtém a exceção no caso de falha de conexão quando um DnsEndPoint foi usado. |
ConnectSocket |
O objeto Socket criado e conectado após a conclusão bem-sucedida do método ConnectAsync. |
Count |
Obtém a quantidade máxima de dados, em bytes, a ser enviada ou recebida em uma operação assíncrona. |
DisconnectReuseSocket |
Obtém ou define um valor que especifica se o soquete poderá ser reutilizado após uma operação de desconexão. |
LastOperation |
Obtém o tipo de operação de soquete executada mais recentemente com esse objeto de contexto. |
MemoryBuffer |
Obtém a região de memória a ser usada como um buffer com um método de soquete assíncrono. |
Offset |
Obtém o deslocamento, em bytes, para o buffer de dados referenciado pela propriedade Buffer. |
ReceiveMessageFromPacketInfo |
Obtém o endereço IP e a interface de um pacote recebido. |
RemoteEndPoint |
Obtém ou define o ponto de extremidade IP remoto para uma operação assíncrona. |
SendPacketsElements |
Obtém ou define uma matriz de buffers a ser enviada para uma operação assíncrona usada pelo método SendPacketsAsync(SocketAsyncEventArgs). |
SendPacketsFlags |
Obtém ou define uma combinação bit a bit de valores TransmitFileOptions para uma operação assíncrona usada pelo método SendPacketsAsync(SocketAsyncEventArgs). |
SendPacketsSendSize |
Obtém ou define o tamanho, em bytes, do bloco de dados usado na operação de envio. |
SocketClientAccessPolicyProtocol |
Obsoleto.
Obtém ou define o protocolo a ser usado para baixar o arquivo de política de acesso de cliente do soquete. |
SocketError |
Obtém ou define o resultado da operação de soquete assíncrona. |
SocketFlags |
Obtém os resultados de uma operação de soquete assíncrona ou define o comportamento de uma operação assíncrona. |
UserToken |
Obtém ou define um objeto de usuário ou de aplicativo associado a essa operação de soquete assíncrona. |
Métodos
Dispose() |
Libera os recursos não gerenciados usados pela instância SocketAsyncEventArgs e, opcionalmente, descarta os recursos gerenciados. |
Equals(Object) |
Determina se o objeto especificado é igual ao objeto atual. (Herdado de Object) |
Finalize() |
Libera os recursos usados pela classe SocketAsyncEventArgs. |
GetHashCode() |
Serve como a função de hash padrão. (Herdado de Object) |
GetType() |
Obtém o Type da instância atual. (Herdado de Object) |
MemberwiseClone() |
Cria uma cópia superficial do Object atual. (Herdado de Object) |
OnCompleted(SocketAsyncEventArgs) |
Representa um método chamado quando uma operação assíncrona é concluída. |
SetBuffer(Byte[], Int32, Int32) |
Define o buffer de dados a ser usado com um método de soquete assíncrono. |
SetBuffer(Int32, Int32) |
Define o buffer de dados a ser usado com um método de soquete assíncrono. |
SetBuffer(Memory<Byte>) |
Define a região de memória a ser usada como um buffer com um método de soquete assíncrono. |
ToString() |
Retorna uma cadeia de caracteres que representa o objeto atual. (Herdado de Object) |
Eventos
Completed |
O evento usado para concluir uma operação assíncrona. |
Aplica-se a
Confira também
- IAsyncResult
- Socket
- AcceptAsync(SocketAsyncEventArgs)
- ConnectAsync(SocketAsyncEventArgs)
- DisconnectAsync(SocketAsyncEventArgs)
- ReceiveAsync(SocketAsyncEventArgs)
- ReceiveFromAsync(SocketAsyncEventArgs)
- ReceiveMessageFromAsync(SocketAsyncEventArgs)
- SendAsync(SocketAsyncEventArgs)
- SendPacketsAsync(SocketAsyncEventArgs)
- SendToAsync(SocketAsyncEventArgs)
- Programação de rede no .NET Framework
- Rastreamento de rede no .NET Framework
- Melhorias do desempenho de soquete na versão 3.5