SocketAsyncEventArgs Classe
Definição
Importante
Algumas informações dizem respeito a um produto pré-lançado que pode ser substancialmente modificado antes de ser lançado. A Microsoft não faz garantias, de forma expressa ou implícita, em relação à informação aqui apresentada.
Representa uma operação de soquete assíncrona.
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 seguinte exemplo de código implementa a lógica de ligação para o servidor socket que utiliza a SocketAsyncEventArgs classe. Após aceitar uma ligação, todos os dados lidos pelo cliente são enviados de volta ao cliente. A leitura e o eco de volta ao padrão cliente continuam até que o cliente se desconecte. A classe BufferManager usada por este exemplo é apresentada no exemplo de código do SetBuffer(Byte[], Int32, Int32) método. A classe SocketAsyncEventArgsPool usada neste exemplo é apresentada 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);
}
}
Observações
A SocketAsyncEventArgs classe faz parte de um conjunto de melhorias que System.Net.Sockets.Socket fornecem um padrão assíncrono alternativo que pode ser utilizado por aplicações especializadas de soquetes de alto desempenho. Esta classe foi especificamente concebida para aplicações de servidor de rede que requerem alto desempenho. Uma aplicação pode usar o padrão assíncrono melhorado exclusivamente ou apenas em áreas de alta intensidade (por exemplo, ao receber grandes quantidades de dados).
A principal característica destas melhorias é a evitação da alocação e sincronização repetidas de objetos durante entradas/saídas assíncronas de grande volume. O padrão de design Início/Fim atualmente implementado pela System.Net.Sockets.Socket classe requer que um System.IAsyncResult objeto seja alocado para cada operação de soquete assíncrono.
Nas novas System.Net.Sockets.Socket melhorias de classe, as operações de socket assíncronas são descritas por objetos reutilizáveis SocketAsyncEventArgs alocados e mantidos pela aplicação. As aplicações de soquetes de alto desempenho conhecem melhor a quantidade de operações sobrepostas que devem ser sustentadas. A aplicação pode criar tantos SocketAsyncEventArgs dos objetos quanto precisar. Por exemplo, se uma aplicação servidor precisar de ter 15 operações de aceitação de sockets em curso em todos os momentos para suportar as taxas de ligação do cliente recebido, pode alocar 15 objetos reutilizáveis SocketAsyncEventArgs para esse fim.
O padrão para realizar uma operação assíncrona de soquete com esta classe consiste nos seguintes passos:
Aloca um novo SocketAsyncEventArgs objeto de contexto, ou obtenha um gratuito de um pool de aplicações.
Defina propriedades no objeto de contexto para a operação prestes a ser realizada (o método de callback de completão, o buffer de dados, o deslocamento para o buffer e a quantidade máxima de dados a transferir, por exemplo).
Chame o método do socket apropriado (xxxAsync) para iniciar a operação assíncrona.
Se o método do socket assíncrono (xxxAsync) devolver true, no callback, consulte as propriedades do contexto para o estado de conclusão.
Se o método do socket assíncrono (xxxAsync) devolver falso, a operação foi concluída de forma síncrona. As propriedades de contexto podem ser consultadas para o resultado da operação.
Reutilize o contexto para outra operação, volte a colocá-lo no pool ou descarte-o.
A vida útil do novo objeto de contexto de operação assíncrona do socket é determinada por referências do código de aplicação e referências de E/S assíncronas. Não é necessário que a aplicação mantenha uma referência a um objeto de contexto de operação assíncrona de soquete depois de este ser submetido como parâmetro a um dos métodos de operação assíncrona de soquete. Permanecerá referenciado até que o callback de conclusão regresse. No entanto, é vantajoso para a aplicação manter a referência ao contexto para que possa ser reutilizada numa futura operação de soquete assíncrono.
Construtores
| Name | Description |
|---|---|
| SocketAsyncEventArgs() |
Cria uma instância vazia SocketAsyncEventArgs . |
Propriedades
| Name | Description |
|---|---|
| AcceptSocket |
Obtém ou define o soquete para usar ou o soquete criado para aceitar uma ligação com um método de soquete assíncrono. |
| Buffer |
Obtém o buffer de dados para usar com um método de socket assíncrono. |
| BufferList |
Obtém ou define um array de buffers de dados para usar com um método de socket assíncrono. |
| BytesTransferred |
Obtém o número de bytes transferidos na operação do socket. |
| ConnectByNameError |
Obtém a exceção no caso de falha de ligação quando foi usado a.DnsEndPoint |
| ConnectSocket |
O objeto criado e ligado Socket após a conclusão bem-sucedida do ConnectAsync método. |
| Count |
Obtém a quantidade máxima de dados, em bytes, para enviar ou receber numa operação assíncrona. |
| DisconnectReuseSocket |
Recebe ou define um valor que especifica se o socket pode ser reutilizado após uma operação de desconexão. |
| LastOperation |
Obtém o tipo de operação de socket realizada mais recentemente com este objeto de contexto. |
| MemoryBuffer |
Obtém a região de memória a usar como buffer com um método de socket assíncrono. |
| Offset |
Recebe o deslocamento, em bytes, para o buffer de dados referenciado pela Buffer propriedade. |
| ReceiveMessageFromPacketInfo |
Obtém o endereço IP e a interface de um pacote recebido. |
| RemoteEndPoint |
Obtém ou define o endpoint IP remoto para uma operação assíncrona. |
| SendPacketsElements |
Obtém ou define um array de buffers a serem enviados para uma operação assíncrona usada pelo SendPacketsAsync(SocketAsyncEventArgs) método. |
| SendPacketsFlags |
Obtém ou define uma combinação bit a bit de TransmitFileOptions valores para uma operação assíncrona usada pelo SendPacketsAsync(SocketAsyncEventArgs) método. |
| 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 para descarregar o ficheiro de política de acesso ao cliente socket. |
| SocketError |
Obtém ou define o resultado da operação do soquete assíncrono. |
| 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 utilizador ou aplicação associado a esta operação de socket assíncrona. |
Métodos
| Name | Description |
|---|---|
| Dispose() |
Liberta os recursos não geridos usados pela SocketAsyncEventArgs instância e, opcionalmente, elimina os recursos geridos. |
| Equals(Object) |
Determina se o objeto especificado é igual ao objeto atual. (Herdado de Object) |
| Finalize() |
Liberta recursos usados pela SocketAsyncEventArgs turma. |
| GetHashCode() |
Serve como função de hash predefinida. (Herdado de Object) |
| GetType() |
Obtém o Type da instância atual. (Herdado de Object) |
| MemberwiseClone() |
Cria uma cópia superficial do atual Object. (Herdado de Object) |
| OnCompleted(SocketAsyncEventArgs) |
Representa um método que é chamado quando uma operação assíncrona é concluída. |
| SetBuffer(Byte[], Int32, Int32) |
Define o buffer de dados para ser usado com um método de socket assíncrono. |
| SetBuffer(Int32, Int32) |
Define o buffer de dados para ser usado com um método de socket assíncrono. |
| SetBuffer(Memory<Byte>) |
Define a região de memória para usar como buffer com um método de socket assíncrono. |
| ToString() |
Devolve uma cadeia que representa o objeto atual. (Herdado de Object) |
evento
| Name | Description |
|---|---|
| Completed |
O evento usado para completar uma operação assíncrona. |
Aplica-se a
Ver 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 no desempenho dos soquetes na versão 3.5