SocketAsyncEventArgs Klasa
Definicja
Ważne
Niektóre informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany przed wydaniem. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Reprezentuje operację asynchronicznego gniazda.
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
- Dziedziczenie
- Implementuje
Przykłady
Poniższy przykład kodu implementuje logikę połączenia dla serwera gniazd, który używa SocketAsyncEventArgs klasy . Po zaakceptowaniu połączenia wszystkie dane odczytane z klienta są wysyłane z powrotem do klienta. Odczyt i echo z powrotem do wzorca klienta są kontynuowane do momentu rozłączenia klienta. Klasa BufferManager używana przez ten przykład jest wyświetlana w przykładzie SetBuffer(Byte[], Int32, Int32) kodu dla metody . Klasa SocketAsyncEventArgsPool używana w tym przykładzie jest wyświetlana w przykładzie kodu konstruktora 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);
}
}
Uwagi
Klasa SocketAsyncEventArgs jest częścią zestawu ulepszeń System.Net.Sockets.Socket klasy, które zapewniają alternatywny wzorzec asynchroniczny, który może być używany przez wyspecjalizowane aplikacje gniazd o wysokiej wydajności. Ta klasa została specjalnie zaprojektowana dla aplikacji serwera sieciowego, które wymagają wysokiej wydajności. Aplikacja może używać rozszerzonego wzorca asynchronicznego wyłącznie lub tylko w docelowych obszarach gorących (na przykład podczas odbierania dużych ilości danych).
Główną cechą tych ulepszeń jest unikanie powtarzającej się alokacji i synchronizacji obiektów podczas operacji we/wy gniazda asynchronicznego o dużej ilości. Wzorzec projektu Początek/Koniec, który jest obecnie implementowany przez System.Net.Sockets.Socket klasę System.IAsyncResult , wymaga przydzieleniu obiektu dla każdej operacji asynchronicznego gniazda.
W nowych System.Net.Sockets.Socket ulepszeniach klasy operacje asynchronicznego gniazda są opisywane przez obiekty wielokrotnego użytku SocketAsyncEventArgs przydzielone i obsługiwane przez aplikację. Aplikacje gniazd o wysokiej wydajności najlepiej znają ilość nakładających się operacji gniazd, które muszą być trwałe. Aplikacja może utworzyć dowolną liczbę SocketAsyncEventArgs obiektów, których potrzebuje. Jeśli na przykład aplikacja serwera musi mieć 15 gniazd akceptowanych operacji zaległych przez cały czas w celu obsługi przychodzących stawek połączeń klienta, może przydzielić do tego celu 15 obiektów wielokrotnego użytku SocketAsyncEventArgs .
Wzorzec wykonywania operacji asynchronicznego gniazda z tą klasą składa się z następujących kroków:
Przydziel nowy SocketAsyncEventArgs obiekt kontekstu lub uzyskaj bezpłatny obiekt z puli aplikacji.
Ustaw właściwości obiektu kontekstu na operację, która ma zostać wykonana (metoda wywołania zwrotnego ukończenia, bufor danych, przesunięcie do buforu i maksymalna ilość danych do transferu, na przykład).
Wywołaj odpowiednią metodę gniazda (xxxAsync), aby zainicjować operację asynchroniczną.
Jeśli metoda asynchronicznego gniazda (xxxAsync) zwraca wartość true, w wywołaniu zwrotnym wykonaj zapytanie o właściwości kontekstu pod kątem stanu ukończenia.
Jeśli metoda asynchronicznego gniazda (xxxAsync) zwraca wartość false, operacja została ukończona synchronicznie. Właściwości kontekstu mogą być odpytywane dla wyniku operacji.
Ponownie użyj kontekstu dla innej operacji, umieść go z powrotem w puli lub odrzuć.
Okres istnienia nowego obiektu kontekstu operacji asynchronicznego gniazda zależy od odwołań do kodu aplikacji i asynchronicznych odwołań we/wy. Nie jest konieczne, aby aplikacja zachowała odwołanie do obiektu kontekstu operacji asynchronicznego gniazda po przesłaniu go jako parametru do jednej z metod operacji asynchronicznego gniazda. Pozostanie on przywołyny do momentu powrotu wywołania zwrotnego ukończenia. Jednak korzystne jest, aby aplikacja zachowała odwołanie do kontekstu, aby można było go ponownie użyć do przyszłej operacji asynchronicznego gniazda.
Konstruktory
SocketAsyncEventArgs() |
Tworzy puste SocketAsyncEventArgs wystąpienie. |
SocketAsyncEventArgs(Boolean) |
Inicjuje element SocketAsyncEventArgs. |
Właściwości
AcceptSocket |
Pobiera lub ustawia gniazdo do użycia lub gniazdo utworzone do akceptowania połączenia z metodą asynchronicznego gniazda. |
Buffer |
Pobiera bufor danych do użycia z metodą asynchronicznego gniazda. |
BufferList |
Pobiera lub ustawia tablicę buforów danych do użycia z metodą asynchronicznego gniazda. |
BytesTransferred |
Pobiera liczbę bajtów przesyłanych w operacji gniazda. |
ConnectByNameError |
Pobiera wyjątek w przypadku awarii połączenia, gdy DnsEndPoint był używany. |
ConnectSocket |
Utworzony i połączony Socket obiekt po pomyślnym zakończeniu ConnectAsync metody. |
Count |
Pobiera maksymalną ilość danych w bajtach do wysyłania lub odbierania w operacji asynchronicznej. |
DisconnectReuseSocket |
Pobiera lub ustawia wartość określającą, czy gniazdo może zostać ponownie użyte po operacji rozłączenia. |
LastOperation |
Pobiera typ operacji gniazda ostatnio wykonywanej z tym obiektem kontekstu. |
MemoryBuffer |
Pobiera region pamięci do użycia jako bufor z metodą asynchronicznego gniazda. |
Offset |
Pobiera przesunięcie w bajtach do buforu Buffer danych, do których odwołuje się właściwość . |
ReceiveMessageFromPacketInfo |
Pobiera adres IP i interfejs odebranego pakietu. |
RemoteEndPoint |
Pobiera lub ustawia zdalny punkt końcowy adresu IP dla operacji asynchronicznej. |
SendPacketsElements |
Pobiera lub ustawia tablicę buforów do wysłania dla operacji asynchronicznej używanej przez metodę SendPacketsAsync(SocketAsyncEventArgs) . |
SendPacketsFlags |
Pobiera lub ustawia bitową kombinację TransmitFileOptions wartości dla operacji asynchronicznej używanej przez metodę SendPacketsAsync(SocketAsyncEventArgs) . |
SendPacketsSendSize |
Pobiera lub ustawia rozmiar bloku danych używanego w operacji wysyłania w bajtach. |
SocketClientAccessPolicyProtocol |
Przestarzałe.
Pobiera lub ustawia protokół, który ma służyć do pobierania pliku zasad dostępu klienta gniazda. |
SocketError |
Pobiera lub ustawia wynik operacji asynchronicznego gniazda. |
SocketFlags |
Pobiera wyniki operacji asynchronicznego gniazda lub ustawia zachowanie operacji asynchronicznej. |
UserToken |
Pobiera lub ustawia obiekt użytkownika lub aplikacji skojarzony z tą operacją asynchronicznego gniazda. |
Metody
Dispose() |
Zwalnia niezarządzane zasoby używane przez SocketAsyncEventArgs wystąpienie i opcjonalnie usuwa zasoby zarządzane. |
Equals(Object) |
Określa, czy dany obiekt jest taki sam, jak bieżący obiekt. (Odziedziczone po Object) |
Finalize() |
Zwalnia zasoby używane przez klasę SocketAsyncEventArgs . |
GetHashCode() |
Służy jako domyślna funkcja skrótu. (Odziedziczone po Object) |
GetType() |
Type Pobiera bieżące wystąpienie. (Odziedziczone po Object) |
MemberwiseClone() |
Tworzy płytkią kopię bieżącego Objectelementu . (Odziedziczone po Object) |
OnCompleted(SocketAsyncEventArgs) |
Reprezentuje metodę wywoływaną po zakończeniu operacji asynchronicznej. |
SetBuffer(Byte[], Int32, Int32) |
Ustawia bufor danych do użycia z metodą asynchronicznego gniazda. |
SetBuffer(Int32, Int32) |
Ustawia bufor danych do użycia z metodą asynchronicznego gniazda. |
SetBuffer(Memory<Byte>) |
Ustawia region pamięci, który ma być używany jako bufor z asynchroniczną metodą gniazda. |
ToString() |
Zwraca ciąg reprezentujący bieżący obiekt. (Odziedziczone po Object) |
Zdarzenia
Completed |
Zdarzenie używane do ukończenia operacji asynchronicznej. |
Dotyczy
Zobacz też
- IAsyncResult
- Socket
- AcceptAsync(SocketAsyncEventArgs)
- ConnectAsync(SocketAsyncEventArgs)
- DisconnectAsync(SocketAsyncEventArgs)
- ReceiveAsync(SocketAsyncEventArgs)
- ReceiveFromAsync(SocketAsyncEventArgs)
- ReceiveMessageFromAsync(SocketAsyncEventArgs)
- SendAsync(SocketAsyncEventArgs)
- SendPacketsAsync(SocketAsyncEventArgs)
- SendToAsync(SocketAsyncEventArgs)
- Programowanie dla sieci w .NET Framework
- Śledzenie sieci w .NET Framework
- Ulepszenia wydajności gniazda w wersji 3.5