Uso di un socket server asincronoUsing an Asynchronous Server Socket

I socket server asincroni usano il modello di programmazione asincrona di .NET Framework per elaborare le richieste di servizio di rete.Asynchronous server sockets use the .NET Framework asynchronous programming model to process network service requests. La classe Socket segue il modello di denominazione asincrona di .NET Framework standard. Ad esempio, il metodo sincrono Accept corrisponde ai metodi asincroni BeginAccept e EndAccept.The Socket class follows the standard .NET Framework asynchronous naming pattern; for example, the synchronous Accept method corresponds to the asynchronous BeginAccept and EndAccept methods.

Un socket server asincrono richiede un metodo per iniziare ad accettare le richieste di connessione dalla rete, un metodo di callback per gestire le richieste di connessione e iniziare a ricevere dati dalla rete e un metodo di callback per terminare la ricezione dei dati.An asynchronous server socket requires a method to begin accepting connection requests from the network, a callback method to handle the connection requests and begin receiving data from the network, and a callback method to end receiving the data. Tutti questi metodi vengono descritti più avanti in questa sezione.All these methods are discussed further in this section.

Nell'esempio seguente, per iniziare ad accettare le richieste di connessione dalla rete, il metodo StartListening inizializza Socket e quindi usa il metodo BeginAccept per iniziare ad accettare nuove connessioni.In the following example, to begin accepting connection requests from the network, the method StartListening initializes the Socket and then uses the BeginAccept method to start accepting new connections. Il metodo di callback per l'accettazione viene chiamato alla ricezione di una nuova richiesta di connessione sul socket.The accept callback method is called when a new connection request is received on the socket. È responsabile del recupero dell'istanza di Socket che gestirà la connessione e del passaggio di tale Socket al thread che elaborerà la richiesta.It is responsible for getting the Socket instance that will handle the connection and handing that Socket off to the thread that will process the request. Il metodo di callback per l'accettazione implementa il delegato AsyncCallback, restituisce un void e accetta un singolo parametro di tipo IAsyncResult.The accept callback method implements the AsyncCallback delegate; it returns a void and takes a single parameter of type IAsyncResult. L'esempio seguente è la shell di un metodo di callback per l'accettazione.The following example is the shell of an accept callback method.

Sub acceptCallback(ar As IAsyncResult)  
    ' Add the callback code here.  
End Sub 'acceptCallback  
void acceptCallback( IAsyncResult ar) {  
    // Add the callback code here.  
}  

Il metodo BeginAccept accetta due parametri, un delegato AsyncCallback che punta al metodo di callback per l'accettazione e un oggetto usato per passare le informazioni sullo stato al metodo di callback.The BeginAccept method takes two parameters, an AsyncCallback delegate that points to the accept callback method and an object that is used to pass state information to the callback method. Nell'esempio seguente il Socket in ascolto viene passato al metodo di callback tramite il parametro state.In the following example, the listening Socket is passed to the callback method through the state parameter. Questo esempio crea un delegato AsyncCallback e inizia ad accettare connessioni dalla rete.This example creates an AsyncCallback delegate and starts accepting connections from the network.

listener.BeginAccept( _  
    New AsyncCallback(SocketListener.acceptCallback),_  
    listener)  
listener.BeginAccept(  
    new AsyncCallback(SocketListener.acceptCallback),   
    listener);  

I socket asincroni usano thread dal pool di thread di sistema per elaborare le connessioni in ingresso.Asynchronous sockets use threads from the system thread pool to process incoming connections. Un thread è responsabile dell'accettazione di connessioni, un altro thread viene usato per gestire ogni connessione in ingresso e un altro thread è responsabile della ricezione di dati dalla connessione.One thread is responsible for accepting connections, another thread is used to handle each incoming connection, and another thread is responsible for receiving data from the connection. Può trattarsi dello stesso thread, a seconda di quale thread viene assegnato dal pool di thread.These could be the same thread, depending on which thread is assigned by the thread pool. Nell'esempio seguente la classe System.Threading.ManualResetEvent sospende l'esecuzione del thread principale e segnala quando l'esecuzione può continuare.In the following example, the System.Threading.ManualResetEvent class suspends execution of the main thread and signals when execution can continue.

L'esempio seguente mostra un metodo asincrono che crea un socket TCP/IP asincrono nel computer locale e inizia ad accettare connessioni.The following example shows an asynchronous method that creates an asynchronous TCP/IP socket on the local computer and begins accepting connections. Si presuppone che esista un ManualResetEvent globale denominato allDone, che il metodo sia un membro di una classe denominata SocketListener e che sia stato definito un metodo di callback denominato acceptCallback.It assumes that there is a global ManualResetEvent named allDone, that the method is a member of a class named SocketListener, and that a callback method named acceptCallback is defined.

Public Sub StartListening()  
    Dim ipHostInfo As IPHostEntry = Dns.Resolve(Dns.GetHostName())  
    Dim localEP = New IPEndPoint(ipHostInfo.AddressList(0), 11000)  

    Console.WriteLine("Local address and port : {0}", localEP.ToString())  

    Dim listener As New Socket(localEP.Address.AddressFamily, _  
       SocketType.Stream, ProtocolType.Tcp)  

    Try  
        listener.Bind(localEP)  
        listener.Listen(10)  

        While True  
            allDone.Reset()  

            Console.WriteLine("Waiting for a connection...")  
            listener.BeginAccept(New _  
                AsyncCallback(SocketListener.acceptCallback), _  
                listener)  

            allDone.WaitOne()  
        End While  
    Catch e As Exception  
        Console.WriteLine(e.ToString())  
    End Try  
    Console.WriteLine("Closing the listener...")  
End Sub 'StartListening  
public void StartListening() {  
    IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());  
    IPEndPoint localEP = new IPEndPoint(ipHostInfo.AddressList[0],11000);  

    Console.WriteLine("Local address and port : {0}",localEP.ToString());  

    Socket listener = new Socket( localEP.Address.AddressFamily,  
        SocketType.Stream, ProtocolType.Tcp );  

    try {  
        listener.Bind(localEP);  
        listener.Listen(10);  

        while (true) {  
            allDone.Reset();  

            Console.WriteLine("Waiting for a connection...");  
            listener.BeginAccept(  
                new AsyncCallback(SocketListener.acceptCallback),   
                listener );  

            allDone.WaitOne();  
        }  
    } catch (Exception e) {  
        Console.WriteLine(e.ToString());  
    }  

    Console.WriteLine( "Closing the listener...");  
}  

Il metodo di callback per l'accettazione (acceptCallback nell'esempio precedente) ha la responsabilità di segnalare al thread principale dell'applicazione di continuare l'elaborazione, di stabilire la connessione con il client e di avviare la lettura asincrona dei dati dal client.The accept callback method (acceptCallback in the preceding example) is responsible for signaling the main application thread to continue processing, establishing the connection with the client, and starting the asynchronous read of data from the client. L'esempio seguente è la prima parte di un'implementazione del metodo acceptCallback.The following example is the first part of an implementation of the acceptCallback method. Questa sezione del metodo segnala al thread principale dell'applicazione di continuare l'elaborazione e stabilisce la connessione al client.This section of the method signals the main application thread to continue processing and establishes the connection to the client. Si presuppone l'esistenza di un ManualResetEvent globale denominato allDone.It assumes a global ManualResetEvent named allDone.

Public Sub acceptCallback(ar As IAsyncResult)  
    allDone.Set()  

    Dim listener As Socket = CType(ar.AsyncState, Socket)  
    Dim handler As Socket = listener.EndAccept(ar)  

    ' Additional code to read data goes here.  
End Sub 'acceptCallback  
public void acceptCallback(IAsyncResult ar) {  
    allDone.Set();  

    Socket listener = (Socket) ar.AsyncState;  
    Socket handler = listener.EndAccept(ar);  

    // Additional code to read data goes here.    
}  

Per la lettura dei dati da un socket client è necessario un oggetto stato che passa i valori tra chiamate asincrone.Reading data from a client socket requires a state object that passes values between asynchronous calls. L'esempio seguente implementa un oggetto di stato per la ricezione di una stringa dal client remoto.The following example implements a state object for receiving a string from the remote client. Contiene i campi per il socket client, un buffer di dati per la ricezione dei dati e un StringBuilder per creare la stringa di dati inviata dal client.It contains fields for the client socket, a data buffer for receiving data, and a StringBuilder for creating the data string sent by the client. Il posizionamento di questi campi nell'oggetto stato consente di mantenerne i valori tra più chiamate per leggere i dati dal socket client.Placing these fields in the state object allows their values to be preserved across multiple calls to read data from the client socket.

Public Class StateObject  
    Public workSocket As Socket = Nothing  
    Public BufferSize As Integer = 1024  
    Public buffer(BufferSize) As Byte  
    Public sb As New StringBuilder()  
End Class 'StateObject  
public class StateObject {  
    public Socket workSocket = null;  
    public const int BufferSize = 1024;  
    public byte[] buffer = new byte[BufferSize];  
    public StringBuilder sb = new StringBuilder();  
}  

La sezione del metodo acceptCallback che avvia la ricezione dei dati dal socket client inizializza prima di tutto un'istanza della classe StateObject e quindi chiama il metodo BeginReceive per avviare la lettura dei dati dal socket client in modo asincrono.The section of the acceptCallback method that starts receiving the data from the client socket first initializes an instance of the StateObject class and then calls the BeginReceive method to start reading the data from the client socket asynchronously.

L'esempio seguente mostra il metodo acceptCallback completo.The following example shows the complete acceptCallback method. Si presuppone che esista un ManualResetEvent globale denominato allDone,, che sia stata definita la classe StateObject e che sia stato definito il metodo readCallback in una classe denominata SocketListener.It assumes that there is a global ManualResetEvent named allDone, that the StateObject class is defined, and that the readCallback method is defined in a class named SocketListener.

Public Shared Sub acceptCallback(ar As IAsyncResult)  
    ' Get the socket that handles the client request.  
    Dim listener As Socket = CType(ar.AsyncState, Socket)  
    Dim handler As Socket = listener.EndAccept(ar)  

    ' Signal the main thread to continue.  
    allDone.Set()  

    ' Create the state object.  
    Dim state As New StateObject()  
    state.workSocket = handler  
    handler.BeginReceive(state.buffer, 0, state.BufferSize, 0, _  
        AddressOf AsynchronousSocketListener.readCallback, state)  
End Sub 'acceptCallback  
public static void acceptCallback(IAsyncResult ar) {  
    // Get the socket that handles the client request.  
    Socket listener = (Socket) ar.AsyncState;  
    Socket handler = listener.EndAccept(ar);  

    // Signal the main thread to continue.  
    allDone.Set();  

    // Create the state object.  
    StateObject state = new StateObject();  
    state.workSocket = handler;  
    handler.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,  
        new AsyncCallback(AsynchronousSocketListener.readCallback), state);  
}  

Il metodo finale che deve essere implementato per il socket server asincrono è il metodo di callback per la lettura che restituisce i dati inviati dal client.The final method that needs to be implemented for the asynchronous socket server is the read callback method that returns the data sent by the client. Come nel caso del metodo di callback per l'accettazione, il metodo di callback per la lettura è un delegato AsyncCallback.Like the accept callback method, the read callback method is an AsyncCallback delegate. Questo metodo legge uno o più byte dal socket client nel buffer di dati e quindi chiama di nuovo il metodo BeginReceive fino al completamento dei dati inviati dal client.This method reads one or more bytes from the client socket into the data buffer and then calls the BeginReceive method again until the data sent by the client is complete. Quando l'intero messaggio è stato letto dal client, la stringa viene visualizzata nella console e il socket server che gestisce la connessione al client viene chiuso.Once the entire message has been read from the client, the string is displayed on the console and the server socket handling the connection to the client is closed.

L'esempio seguente implementa il metodo readCallback.The following sample implements the readCallback method. Si presuppone che la classe StateObject sia definita.It assumes that the StateObject class is defined.

Public Shared Sub readCallback(ar As IAsyncResult)  
    Dim state As StateObject = CType(ar.AsyncState, StateObject)  
    Dim handler As Socket = state.workSocket  

    ' Read data from the client socket.   
    Dim read As Integer = handler.EndReceive(ar)  

    ' Data was read from the client socket.  
    If read > 0 Then  
        state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, read))  
        handler.BeginReceive(state.buffer, 0, state.BufferSize, 0, _  
            AddressOf readCallback, state)  
    Else  
        If state.sb.Length > 1 Then  
            ' All the data has been read from the client;  
            ' display it on the console.  
            Dim content As String = state.sb.ToString()  
            Console.WriteLine("Read {0} bytes from socket." + _  
                ControlChars.Cr + " Data : {1}", content.Length, content)  
        End If  
    End If  
End Sub 'readCallback  
public static void readCallback(IAsyncResult ar) {  
    StateObject state = (StateObject) ar.AsyncState;  
    Socket handler = state.WorkSocket;  

    // Read data from the client socket.  
    int read = handler.EndReceive(ar);  

    // Data was read from the client socket.  
    if (read > 0) {  
        state.sb.Append(Encoding.ASCII.GetString(state.buffer,0,read));  
        handler.BeginReceive(state.buffer,0,StateObject.BufferSize, 0,  
            new AsyncCallback(readCallback), state);  
    } else {  
        if (state.sb.Length > 1) {  
            // All the data has been read from the client;  
            // display it on the console.  
            string content = state.sb.ToString();  
            Console.WriteLine("Read {0} bytes from socket.\n Data : {1}",  
               content.Length, content);  
        }  
        handler.Close();  
    }  
}  

Vedere ancheSee Also

Uso di un socket server sincronoUsing a Synchronous Server Socket
Esempio di socket server asincronoAsynchronous Server Socket Example
ThreadingThreading
Attesa con socketListening with Sockets