Introduzione a Websocket per Connessioni ibride di Inoltro di Azure in .NET
In questa guida introduttiva vengono create applicazioni mittente e ricevitore .NET che inviano e ricevono messaggi usando Websocket di Connessioni ibride in Inoltro di Azure. Per informazioni di carattere generale su Inoltro di Azure, vedere Che cos'è il servizio di inoltro di Azure?.
In questa guida introduttiva vengono completati i passaggi seguenti:
- Creare uno spazio dei nomi di inoltro usando il portale di Azure.
- Creare una connessione ibrida nello spazio dei nomi usando il portale di Azure.
- Scrivere un'applicazione console server (listener) per ricevere messaggi.
- Scrivere un'applicazione console client (mittente) per inviare messaggi.
- Eseguire le applicazioni.
Prerequisiti
Per completare questa esercitazione è necessario soddisfare i prerequisiti seguenti:
- Visual Studio 2015 o versione successiva. Negli esempi di questa esercitazione viene usato Visual Studio 2017.
- Una sottoscrizione di Azure. Se non se ne dispone, creare un account gratuito prima di iniziare.
Creare uno spazio dei nomi
Accedere al portale di Azure.
Scegliere Tutti i servizi dal menu a sinistra. Selezionare Integrazione, cercare Inoltro, spostare il mouse su Inoltro e quindi selezionare Crea.
Nella pagina Crea spazio dei nomi seguire questa procedura:
Scegliere una sottoscrizione di Azure in cui creare lo spazio dei nomi.
Per Gruppo di risorse scegliere un gruppo di risorse esistente in cui inserire lo spazio dei nomi oppure crearne uno nuovo.
Immettere un nome per lo spazio dei nomi Relay.
Selezionare l'area in cui deve essere ospitato lo spazio dei nomi.
Selezionare Rivedi e crea nella parte inferiore della pagina.
Nella pagina Rivedi e crea selezionare Crea.
Dopo alcuni minuti viene visualizzata la pagina Inoltro per lo spazio dei nomi .
Ottenere le credenziali di gestione
Nella pagina Inoltro selezionare Criteri di accesso condiviso nel menu a sinistra. `
Nella pagina Criteri di accesso condiviso selezionare RootManageSharedAccessKey.
In Criteri di firma di accesso condiviso: RootManageSharedAccessKey selezionare il pulsante Copia accanto a Stringa di connessione primaria. La stringa di connessione viene copiata negli Appunti per un uso successivo. Incollare questo valore nel Blocco note o in un'altra posizione temporanea.
Ripetere il passaggio precedente per copiare e incollare il valore di Chiave primaria in un percorso temporaneo per usarlo in seguito.
Creare una connessione ibrida
Nella pagina Inoltro per lo spazio dei nomi seguire questa procedura per creare una connessione ibrida.
Nel menu a sinistra, in Entità selezionare Connessioni ibride e quindi + Connessione ibrida.
Nella pagina Crea connessione ibrida immettere un nome per la connessione ibrida e selezionare Crea.
Creare un'applicazione server (listener)
In Visual Studio scrivere un'applicazione console in C# per ascoltare e ricevere messaggi dall'inoltro.
Creare un'applicazione console
In Visual Studio creare un nuovo progetto App console (.NET Framework).
Aggiungere il pacchetto NuGet di inoltro
- Fare clic con il pulsante destro del mouse sul progetto appena creato e quindi scegliere Gestisci pacchetti NuGet.
- Selezionare Sfoglia e quindi cercare Microsoft.Azure.Relay. Nei risultati della ricerca selezionare Inoltro di Microsoft Azure.
- Selezionare Installa per completare l'installazione. Chiudere la finestra di dialogo.
Scrivere codice per ricevere messaggi
All'inizio del file Program.cs sostituire le istruzioni
using
esistenti con le istruzioniusing
seguenti:using System; using System.IO; using System.Threading; using System.Threading.Tasks; using System.Net; using Microsoft.Azure.Relay;
Aggiungere costanti alla classe
Program
per i dettagli della connessione ibrida. Sostituire i segnaposto con i valori ottenuti al momento della creazione della connessione ibrida. Usare il nome completo dello spazio dei nomi.// replace {RelayNamespace} with the name of your namespace private const string RelayNamespace = "YOUR-RELAY-NAMESPACE-NAME.servicebus.windows.net"; // replace {HybridConnectionName} with the name of your hybrid connection private const string ConnectionName = "HYBRID-CONNECTION-NAME"; // replace {SAKKeyName} with the name of your Shared Access Policies key, which is RootManageSharedAccessKey by default private const string KeyName = "SAS-KEY-NAME"; // replace {SASKey} with the primary key of the namespace you saved earlier private const string Key = "SAS-KEY-VALUE";
Aggiungere il metodo
ProcessMessagesOnConnection
alla classeProgram
:// The method initiates the connection. private static async void ProcessMessagesOnConnection(HybridConnectionStream relayConnection, CancellationTokenSource cts) { Console.WriteLine("New session"); // The connection is a fully bidrectional stream. // Put a stream reader and a stream writer over it. // This allows you to read UTF-8 text that comes from // the sender, and to write text replies back. var reader = new StreamReader(relayConnection); var writer = new StreamWriter(relayConnection) { AutoFlush = true }; while (!cts.IsCancellationRequested) { try { // Read a line of input until a newline is encountered. var line = await reader.ReadLineAsync(); if (string.IsNullOrEmpty(line)) { // If there's no input data, signal that // you will no longer send data on this connection, // and then break out of the processing loop. await relayConnection.ShutdownAsync(cts.Token); break; } // Write the line on the console. Console.WriteLine(line); // Write the line back to the client, prepended with "Echo:" await writer.WriteLineAsync($"Echo: {line}"); } catch (IOException) { // Catch an I/O exception. This likely occurred when // the client disconnected. Console.WriteLine("Client closed connection"); break; } } Console.WriteLine("End session"); // Close the connection. await relayConnection.CloseAsync(cts.Token); }
Aggiungere il metodo
RunAsync
alla classeProgram
:private static async Task RunAsync() { var cts = new CancellationTokenSource(); var tokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(KeyName, Key); var listener = new HybridConnectionListener(new Uri(string.Format("sb://{0}/{1}", RelayNamespace, ConnectionName)), tokenProvider); // Subscribe to the status events. listener.Connecting += (o, e) => { Console.WriteLine("Connecting"); }; listener.Offline += (o, e) => { Console.WriteLine("Offline"); }; listener.Online += (o, e) => { Console.WriteLine("Online"); }; // Opening the listener establishes the control channel to // the Azure Relay service. The control channel is continuously // maintained, and is reestablished when connectivity is disrupted. await listener.OpenAsync(cts.Token); Console.WriteLine("Server listening"); // Provide callback for the cancellation token that will close the listener. cts.Token.Register(() => listener.CloseAsync(CancellationToken.None)); // Start a new thread that will continuously read the console. new Task(() => Console.In.ReadLineAsync().ContinueWith((s) => { cts.Cancel(); })).Start(); // Accept the next available, pending connection request. // Shutting down the listener allows a clean exit. // This method returns null. while (true) { var relayConnection = await listener.AcceptConnectionAsync(); if (relayConnection == null) { break; } ProcessMessagesOnConnection(relayConnection, cts); } // Close the listener after you exit the processing loop. await listener.CloseAsync(cts.Token); }
Aggiungere la riga di codice seguente al metodo
Main
nella classeProgram
:RunAsync().GetAwaiter().GetResult();
Il file Program.cs completato avrà l'aspetto seguente:
namespace Server { using System; using System.IO; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Relay; public class Program { private const string RelayNamespace = "{RelayNamespace}.servicebus.windows.net"; private const string ConnectionName = "{HybridConnectionName}"; private const string KeyName = "{SASKeyName}"; private const string Key = "{SASKey}"; public static void Main(string[] args) { RunAsync().GetAwaiter().GetResult(); } private static async Task RunAsync() { var cts = new CancellationTokenSource(); var tokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(KeyName, Key); var listener = new HybridConnectionListener(new Uri(string.Format("sb://{0}/{1}", RelayNamespace, ConnectionName)), tokenProvider); // Subscribe to the status events. listener.Connecting += (o, e) => { Console.WriteLine("Connecting"); }; listener.Offline += (o, e) => { Console.WriteLine("Offline"); }; listener.Online += (o, e) => { Console.WriteLine("Online"); }; // Opening the listener establishes the control channel to // the Azure Relay service. The control channel is continuously // maintained, and is reestablished when connectivity is disrupted. await listener.OpenAsync(cts.Token); Console.WriteLine("Server listening"); // Provide callback for a cancellation token that will close the listener. cts.Token.Register(() => listener.CloseAsync(CancellationToken.None)); // Start a new thread that will continuously read the console. new Task(() => Console.In.ReadLineAsync().ContinueWith((s) => { cts.Cancel(); })).Start(); // Accept the next available, pending connection request. // Shutting down the listener allows a clean exit. // This method returns null. while (true) { var relayConnection = await listener.AcceptConnectionAsync(); if (relayConnection == null) { break; } ProcessMessagesOnConnection(relayConnection, cts); } // Close the listener after you exit the processing loop. await listener.CloseAsync(cts.Token); } private static async void ProcessMessagesOnConnection(HybridConnectionStream relayConnection, CancellationTokenSource cts) { Console.WriteLine("New session"); // The connection is a fully bidrectional stream. // Put a stream reader and a stream writer over it. // This allows you to read UTF-8 text that comes from // the sender, and to write text replies back. var reader = new StreamReader(relayConnection); var writer = new StreamWriter(relayConnection) { AutoFlush = true }; while (!cts.IsCancellationRequested) { try { // Read a line of input until a newline is encountered. var line = await reader.ReadLineAsync(); if (string.IsNullOrEmpty(line)) { // If there's no input data, signal that // you will no longer send data on this connection. // Then, break out of the processing loop. await relayConnection.ShutdownAsync(cts.Token); break; } // Write the line on the console. Console.WriteLine(line); // Write the line back to the client, prepended with "Echo:" await writer.WriteLineAsync($"Echo: {line}"); } catch (IOException) { // Catch an I/O exception. This likely occurred when // the client disconnected. Console.WriteLine("Client closed connection"); break; } } Console.WriteLine("End session"); // Close the connection. await relayConnection.CloseAsync(cts.Token); } } }
Creare un'applicazione client (mittente)
In Visual Studio scrivere un'applicazione console in C# per inviare messaggi all'inoltro.
Creare un'applicazione console
In Visual Studio creare un nuovo progetto App console (.NET Framework).
Aggiungere il pacchetto NuGet di inoltro
- Fare clic con il pulsante destro del mouse sul progetto appena creato e quindi scegliere Gestisci pacchetti NuGet.
- Selezionare Sfoglia e quindi cercare Microsoft.Azure.Relay. Nei risultati della ricerca selezionare Inoltro di Microsoft Azure.
- Selezionare Installa per completare l'installazione. Chiudere la finestra di dialogo.
Scrivere codice per inviare messaggi
All'inizio del file Program.cs sostituire le istruzioni
using
esistenti con le istruzioniusing
seguenti:using System; using System.IO; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Relay;
Aggiungere costanti alla classe
Program
per i dettagli della connessione ibrida. Sostituire i segnaposto con i valori ottenuti al momento della creazione della connessione ibrida. Usare il nome completo dello spazio dei nomi.// replace {RelayNamespace} with the name of your namespace private const string RelayNamespace = "YOUR-RELAY-NAMESPACE-NAME.servicebus.windows.net"; // replace {HybridConnectionName} with the name of your hybrid connection private const string ConnectionName = "HYBRID-CONNECTION-NAME"; // replace {SAKKeyName} with the name of your Shared Access Policies key, which is RootManageSharedAccessKey by default private const string KeyName = "SAS-KEY-NAME"; // replace {SASKey} with the primary key of the namespace you saved earlier private const string Key = "SAS-KEY-VALUE";
Aggiungere il metodo seguente alla classe
Program
:private static async Task RunAsync() { Console.WriteLine("Enter lines of text to send to the server with ENTER"); // Create a new hybrid connection client. var tokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(KeyName, Key); var client = new HybridConnectionClient(new Uri(String.Format("sb://{0}/{1}", RelayNamespace, ConnectionName)), tokenProvider); // Initiate the connection. var relayConnection = await client.CreateConnectionAsync(); // Run two concurrent loops on the connection. One // reads input from the console and writes it to the connection // with a stream writer. The other reads lines of input from the // connection with a stream reader and writes them to the console. // Entering a blank line shuts down the write task after // sending it to the server. The server then cleanly shuts down // the connection, which terminates the read task. var reads = Task.Run(async () => { // Initialize the stream reader over the connection. var reader = new StreamReader(relayConnection); var writer = Console.Out; do { // Read a full line of UTF-8 text up to newline. string line = await reader.ReadLineAsync(); // If the string is empty or null, you are done. if (String.IsNullOrEmpty(line)) break; // Write to the console. await writer.WriteLineAsync(line); } while (true); }); // Read from the console and write to the hybrid connection. var writes = Task.Run(async () => { var reader = Console.In; var writer = new StreamWriter(relayConnection) { AutoFlush = true }; do { // Read a line from the console. string line = await reader.ReadLineAsync(); // Write the line out, also when it's empty. await writer.WriteLineAsync(line); // Quit when the line is empty, if (String.IsNullOrEmpty(line)) break; } while (true); }); // Wait for both tasks to finish. await Task.WhenAll(reads, writes); await relayConnection.CloseAsync(CancellationToken.None); }
Aggiungere la riga di codice seguente al metodo
Main
nella classeProgram
.RunAsync().GetAwaiter().GetResult();
Program.cs dovrebbe avere l'aspetto seguente:
using System; using System.IO; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Relay; namespace Client { class Program { private const string RelayNamespace = "{RelayNamespace}.servicebus.windows.net"; private const string ConnectionName = "{HybridConnectionName}"; private const string KeyName = "{SASKeyName}"; private const string Key = "{SASKey}"; static void Main(string[] args) { RunAsync().GetAwaiter().GetResult(); } private static async Task RunAsync() { Console.WriteLine("Enter lines of text to send to the server with ENTER"); // Create a new hybrid connection client. var tokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(KeyName, Key); var client = new HybridConnectionClient(new Uri(String.Format("sb://{0}/{1}", RelayNamespace, ConnectionName)), tokenProvider); // Initiate the connection. var relayConnection = await client.CreateConnectionAsync(); // Run two concurrent loops on the connection. One // reads input from the console and then writes it to the connection // with a stream writer. The other reads lines of input from the // connection with a stream reader and then writes them to the console. // Entering a blank line shuts down the write task after // sending it to the server. The server then cleanly shuts down // the connection, which terminates the read task. var reads = Task.Run(async () => { // Initialize the stream reader over the connection. var reader = new StreamReader(relayConnection); var writer = Console.Out; do { // Read a full line of UTF-8 text up to newline. string line = await reader.ReadLineAsync(); // If the string is empty or null, you are done. if (String.IsNullOrEmpty(line)) break; // Write to the console. await writer.WriteLineAsync(line); } while (true); }); // Read from the console and write to the hybrid connection. var writes = Task.Run(async () => { var reader = Console.In; var writer = new StreamWriter(relayConnection) { AutoFlush = true }; do { // Read a line from the console. string line = await reader.ReadLineAsync(); // Write the line out, also when it's empty. await writer.WriteLineAsync(line); // Quit when the line is empty. if (String.IsNullOrEmpty(line)) break; } while (true); }); // Wait for both tasks to finish. await Task.WhenAll(reads, writes); await relayConnection.CloseAsync(CancellationToken.None); } } }
Nota
Il codice di esempio in questo articolo usa un stringa di connessione per eseguire l'autenticazione in uno spazio dei nomi di Inoltro di Azure per semplificare l'esercitazione. È consigliabile usare l'autenticazione con ID Entra di Microsoft negli ambienti di produzione, invece di usare stringa di connessione o firme di accesso condiviso, che possono essere compromesse più facilmente. Per informazioni dettagliate e codice di esempio per l'uso dell'autenticazione di Microsoft Entra ID, vedere Autenticare e autorizzare un'applicazione con Microsoft Entra ID per accedere alle entità di inoltro di Azure e Autenticare un'identità gestita con Microsoft Entra ID per accedere alle risorse di Inoltro di Azure.
Eseguire le applicazioni
Eseguire l'applicazione server.
Eseguire l'applicazione client e immettere il testo.
Assicurarsi che la console dell'applicazione server visualizzi il testo immesso nell'applicazione client.
È stata creata un'applicazione completa per le connessioni ibride.
Passaggi successivi
In questa guida introduttiva sono state create applicazioni client e server .NET che usano WebSocket per inviare e ricevere messaggi. La funzionalità Connessioni ibride di Inoltro di Azure supporta anche l'uso di HTTP per l'invio e la ricezione di messaggi. Per informazioni sull'uso di HTTP con Connessioni ibride di Inoltro di Azure, vedere la guida introduttiva di HTTP.
In questa guida introduttiva è stato usato .NET Framework per creare applicazioni client e server. Per informazioni su come scrivere applicazioni client e server con Node.js, vedere la guida introduttiva di WebSocket per Node.js o la guida introduttiva di HTTP per Node.js.