SocketAsyncEventArgs Класс
Определение
Важно!
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Представляет асинхронную операцию сокета.
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
- Наследование
- Реализации
Примеры
В следующем примере кода реализуется логика подключения для сервера сокетов, использующего SocketAsyncEventArgs класс. После принятия подключения все данные, считывающиеся от клиента, отправляются клиенту. Чтение и эхо обратно в шаблон клиента продолжается до тех пор, пока клиент не отключается. Класс BufferManager, используемый этим примером, отображается в примере кода для SetBuffer(Byte[], Int32, Int32) метода. Класс SocketAsyncEventArgsPool, используемый в этом примере, отображается в примере кода для конструктора SocketAsyncEventArgs .
// 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);
}
}
Комментарии
Класс SocketAsyncEventArgs является частью набора улучшений System.Net.Sockets.Socket класса, предоставляющего альтернативный асинхронный шаблон, который можно использовать специализированными приложениями сокетов высокой производительности. Этот класс был специально разработан для сетевых серверных приложений, требующих высокой производительности. Приложение может использовать расширенный асинхронный шаблон исключительно или только в целевых горячих областях (например, при получении больших объемов данных).
Основной особенностью этих улучшений является предотвращение повторного выделения и синхронизации объектов во время ввода-вывода с большим объемом асинхронного сокета. В настоящее время шаблон конструктора Begin/End, реализованный System.Net.Sockets.Socket классом System.IAsyncResult , требует выделения объекта для каждой асинхронной операции сокета.
В новых System.Net.Sockets.Socket улучшениях класса асинхронные операции сокета описываются повторно используемыми SocketAsyncEventArgs объектами, выделенными и поддерживаемыми приложением. Высокопроизводительные приложения сокета знают, что лучше всего выполнять операции с перекрывающимися сокетами, которые должны быть устойчивыми. Приложение может создавать столько SocketAsyncEventArgs объектов, сколько требуется. Например, если серверное приложение должно иметь 15 сокетов принимать операции, выдающиеся в любое время для поддержки входящих скоростей подключения клиента, он может выделить 15 повторно используемых SocketAsyncEventArgs объектов для этой цели.
Шаблон выполнения асинхронной операции сокета с этим классом состоит из следующих шагов:
Выделите новый объект контекста или получите бесплатный объект SocketAsyncEventArgs из пула приложений.
Задайте свойства в объекте контекста операцию, выполняемую (метод обратного вызова завершения, буфер данных, смещение в буфер и максимальный объем данных для передачи, например).
Вызовите соответствующий метод сокета (xxxAsync), чтобы инициировать асинхронную операцию.
Если метод асинхронного сокета (xxxAsync) возвращает значение true, в обратном вызове запросите свойства контекста для состояния завершения.
Если асинхронный метод сокета (xxxAsync) возвращает значение false, операция выполняется синхронно. Свойства контекста могут запрашиваться для результата операции.
Повторно используйте контекст для другой операции, поместите его обратно в пул или удалите его.
Время существования нового объекта контекста асинхронной операции сокета определяется ссылками на код приложения и асинхронные ссылки на операции ввода-вывода. Приложению не нужно сохранять ссылку на объект контекста асинхронной операции сокета после отправки в качестве параметра одному из методов асинхронной операции сокета. Ссылка будет оставаться на ней до тех пор, пока обратный вызов завершения не возвращается. Однако приложение может сохранить ссылку на контекст, чтобы ее можно было повторно использовать для будущей асинхронной операции сокета.
Конструкторы
| Имя | Описание |
|---|---|
| SocketAsyncEventArgs() |
Создает пустой SocketAsyncEventArgs экземпляр. |
| SocketAsyncEventArgs(Boolean) |
Инициализирует объект SocketAsyncEventArgs. |
Свойства
| Имя | Описание |
|---|---|
| AcceptSocket |
Возвращает или задает сокет для использования или сокета, созданного для принятия соединения с асинхронным методом сокета. |
| Buffer |
Возвращает буфер данных, используемый с асинхронным методом сокета. |
| BufferList |
Возвращает или задает массив буферов данных для использования с асинхронным методом сокета. |
| BytesTransferred |
Возвращает количество байтов, передаваемых в операции сокета. |
| ConnectByNameError |
Возвращает исключение в случае сбоя подключения при DnsEndPoint использовании. |
| ConnectSocket |
Созданный и подключенный Socket объект после успешного ConnectAsync завершения метода. |
| Count |
Получает максимальный объем данных в байтах для отправки или получения в асинхронной операции. |
| DisconnectReuseSocket |
Возвращает или задает значение, указывающее, можно ли повторно использовать сокет после операции отключения. |
| LastOperation |
Возвращает тип операции сокета, недавно выполняемой с этим объектом контекста. |
| MemoryBuffer |
Возвращает область памяти, используемую в качестве буфера с асинхронным методом сокета. |
| Offset |
Возвращает смещение в байтах в буфер данных, на который ссылается Buffer свойство. |
| ReceiveMessageFromPacketInfo |
Возвращает IP-адрес и интерфейс полученного пакета. |
| RemoteEndPoint |
Возвращает или задает удаленную конечную точку IP-адреса для асинхронной операции. |
| SendPacketsElements |
Возвращает или задает массив буферов, отправляемых для асинхронной операции, используемой методом SendPacketsAsync(SocketAsyncEventArgs) . |
| SendPacketsFlags |
Возвращает или задает побитовое сочетание TransmitFileOptions значений для асинхронной операции, используемой методом SendPacketsAsync(SocketAsyncEventArgs) . |
| SendPacketsSendSize |
Возвращает или задает размер блока данных в байтах, используемого в операции отправки. |
| SocketClientAccessPolicyProtocol |
Устаревшие..
Возвращает или задает протокол, используемый для скачивания файла политики доступа клиента сокета. |
| SocketError |
Возвращает или задает результат асинхронной операции сокета. |
| SocketFlags |
Возвращает результаты асинхронной операции сокета или задает поведение асинхронной операции. |
| UserToken |
Возвращает или задает объект пользователя или приложения, связанный с этой асинхронной операцией сокета. |
Методы
| Имя | Описание |
|---|---|
| Dispose() |
Освобождает неуправляемые ресурсы, используемые экземпляром SocketAsyncEventArgs , и при необходимости удаляет управляемые ресурсы. |
| Equals(Object) |
Определяет, равен ли указанный объект текущему объекту. (Унаследовано от Object) |
| Finalize() |
Освобождает ресурсы, используемые классом SocketAsyncEventArgs . |
| GetHashCode() |
Служит хэш-функцией по умолчанию. (Унаследовано от Object) |
| GetType() |
Возвращает Type текущего экземпляра. (Унаследовано от Object) |
| MemberwiseClone() |
Создает неглубокую копию текущей Object. (Унаследовано от Object) |
| OnCompleted(SocketAsyncEventArgs) |
Представляет метод, который вызывается при завершении асинхронной операции. |
| SetBuffer(Byte[], Int32, Int32) |
Задает буфер данных для использования с асинхронным методом сокета. |
| SetBuffer(Int32, Int32) |
Задает буфер данных для использования с асинхронным методом сокета. |
| SetBuffer(Memory<Byte>) |
Задает область памяти, используемую в качестве буфера с асинхронным методом сокета. |
| ToString() |
Возвращает строку, представляющую текущий объект. (Унаследовано от Object) |
События
| Имя | Описание |
|---|---|
| Completed |
Событие, используемое для выполнения асинхронной операции. |
Применяется к
См. также раздел
- IAsyncResult
- Socket
- AcceptAsync(SocketAsyncEventArgs)
- ConnectAsync(SocketAsyncEventArgs)
- DisconnectAsync(SocketAsyncEventArgs)
- ReceiveAsync(SocketAsyncEventArgs)
- ReceiveFromAsync(SocketAsyncEventArgs)
- ReceiveMessageFromAsync(SocketAsyncEventArgs)
- SendAsync(SocketAsyncEventArgs)
- SendPacketsAsync(SocketAsyncEventArgs)
- SendToAsync(SocketAsyncEventArgs)
- Сетевое программирование в .NET Framework
- Трассировка сети в .NET Framework
- Улучшения производительности сокета в версии 3.5