Introduzione alle connessioni ibride di inoltroGet started with Relay Hybrid Connections

Questa esercitazione offre un'introduzione alle connessioni ibride di inoltro di Azure e illustra come usare .NET per creare un'applicazione client che invia messaggi a un'applicazione listener corrispondente.This tutorial provides an introduction to Azure Relay Hybrid Connections, and shows how to use .NET to create a client application that sends messages to a corresponding listener application.

Contenuto dell'esercitazioneWhat will be accomplished

Dato che le connessioni ibride richiedono sia un componente client che un componente server, nel corso dell'esercitazione vengono create due applicazioni console.Because Hybrid Connections requires both a client and a server component, the tutorial creates two console applications. Di seguito sono riportati i passaggi necessari:Here are the steps:

  1. Creare uno spazio dei nomi di inoltro usando il portale di Azure.Create a Relay namespace, using the Azure portal.
  2. Creare una connessione ibrida nello spazio dei nomi usando il portale di Azure.Create a hybrid connection in that namespace, using the Azure portal.
  3. Scrivere un'applicazione console server (listener) per ricevere messaggi.Write a server (listener) console application to receive messages.
  4. Scrivere un'applicazione console client (mittente) per inviare messaggi.Write a client (sender) console application to send messages.

PrerequisitiPrerequisites

Per completare questa esercitazione è necessario soddisfare i prerequisiti seguenti:To complete this tutorial, you'll need the following prerequisites:

  1. Visual Studio 2015 o versione successiva.Visual Studio 2015 or higher. Negli esempi di questa esercitazione viene usato Visual Studio 2017.The examples in this tutorial use Visual Studio 2017.
  2. Una sottoscrizione di Azure.An Azure subscription.

Nota

Per completare l'esercitazione, è necessario un account Azure.To complete this tutorial, you need an Azure account. È possibile attivare i benefici della sottoscrizione MSDN o iscriversi per un account gratuito.You can activate your MSDN subscriber benefits or sign up for a free account.

1. Creare uno spazio dei nomi tramite il portale di Azure1. Create a namespace using the Azure portal

Se è già stato creato uno spazio dei nomi di inoltro, passare alla sezione Creare una connessione ibrida usando il portale di Azure.If you have already created a Relay namespace, jump to the Create a hybrid connection using the Azure portal section.

  1. Accedere al portale di Azure.Log on to the Azure portal.
  2. Nel riquadro di spostamento sinistro del portale fare clic su Nuovo, quindi su Enterprise Integration e infine su Inoltro.In the left navigation pane of the portal, click New, then click Enterprise Integration, and then click Relay.
  3. Nella finestra di dialogo Crea spazio dei nomi immettere un nome per lo spazio dei nomi.In the Create namespace dialog, enter a namespace name. Verrà effettuato immediatamente un controllo sulla disponibilità del nome.The system immediately checks to see if the name is available.
  4. Nel campo Sottoscrizione scegliere una sottoscrizione di Azure in cui creare lo spazio dei nomi.In the Subscription field, choose an Azure subscription in which to create the namespace.
  5. Nel campo Gruppo di risorse scegliere un gruppo di risorse esistente nel quale risiederà lo spazio dei nomi oppure crearne uno nuovo.In the Resource group field, choose an existing resource group in which the namespace will live, or create a new one.
  6. In Localitàscegliere il paese o l'area in cui deve essere ospitato lo spazio dei nomi.In Location, choose the country or region in which your namespace should be hosted.

    Crea spazio dei nomi

  7. Fare clic su Crea.Click Create. A questo punto, lo spazio dei nomi verrà creato e abilitato nel sistema.The system now creates your namespace and enables it. Dopo alcuni minuti, il sistema effettua il provisioning delle risorse per l'account.After a few minutes, the system provisions resources for your account.

Ottenere le credenziali di gestioneObtain the management credentials

  1. Nell'elenco degli spazi dei nomi fare clic sul nome dello spazio dei nomi appena creato.In the list of namespaces, click the newly created namespace name.
  2. Nel pannello dello spazio dei nomi fare clic su Criteri di accesso condivisi.In the namespace blade, click Shared access policies.
  3. Nel pannello Criteri di accesso condivisi fare clic su RootManageSharedAccessKey.In the Shared access policies blade, click RootManageSharedAccessKey.

    connection-info

  4. Nel pannello Criteri: RootManageSharedAccessKey fare clic sul pulsante Copia accanto a Stringa di connessione - chiave primaria per copiare la stringa di connessione negli Appunti e usarla in un secondo momento.In the Policy: RootManageSharedAccessKey blade, click the copy button next to Connection string–primary key, to copy the connection string to your clipboard for later use. Incollare questo valore nel Blocco note o in un'altra posizione temporanea.Paste this value into Notepad or some other temporary location.

    connection-string

  5. Ripetere il passaggio precedente e copiare e incollare il valore della chiave primaria in un percorso temporaneo per usarlo in seguito.Repeat the previous step, copying and pasting the value of Primary key to a temporary location for later use.

2. Creare una connessione ibrida usando il portale di Azure2. Create a hybrid connection using the Azure portal

Se è già stata creata una connessione ibrida, passare alla sezione Creare un'applicazione server.If you have already created a hybrid connection, jump to the Create a server application section.

Verificare che sia già stato creato uno spazio dei nomi di inoltro, come illustrato qui.Ensure that you have already created a Relay namespace, as shown here.

  1. Accedere al portale di Azure.Log on to the Azure portal.
  2. Nel pannello di navigazione sinistro del portale fare clic su Inoltro.In the left navigation pane of the portal, click Relay.
  3. Selezionare lo spazio dei nomi in cui si vuole creare la connessione ibrida.Select the namespace in which you would like to create the Hybrid Connection. In questo caso è mynewns.In this case, it is mynewns.

    Creare una connessione ibrida

  4. Nel pannello Relay namespace (Spazio dei nomi di inoltro) selezionare Connessioni ibride, quindi fare clic su + Connessione ibrida.In the Relay namespace blade, select Hybrid Connections, then click + Hybrid Connection.

    Selezionare la connessione ibrida

  5. Immettere il Nome connessione ibrida e lasciare invariati gli altri valori.Enter the Hybrid Connection Name and leave the other values with their defaults.

    Selezionare Nuovo

  6. Fare clic su Creanella parte inferiore del pannello.At the bottom of the blade, click Create.

3. Creare un'applicazione server (listener)3. Create a server application (listener)

Per ascoltare e ricevere messaggi dall'inoltro, verrà scritta un'applicazione console Node.js usando Visual Studio.To listen and receive messages from the Relay, we will write a C# console application using Visual Studio.

Creare un'applicazione consoleCreate a console application

Avviare Visual Studio e creare un nuovo progetto App console (.NET Framework).First, launch Visual Studio and create a new Console App (.NET Framework) project.

Aggiungere il pacchetto NuGet di inoltroAdd the Relay NuGet package

  1. Fare clic con il pulsante destro del mouse sul progetto appena creato e scegliere Gestisci pacchetti NuGet.Right-click the newly created project and then click Manage NuGet Packages.
  2. Fare clic sulla scheda Sfoglia, quindi cercare "Microsoft.Azure.Relay" e selezionare l'elemento Inoltro di Microsoft Azure.Click the Browse tab, then search for "Microsoft.Azure.Relay" and select the Microsoft Azure Relay item. Fare clic su Installa per completare l'installazione, quindi chiudere questa finestra di dialogo.Click Install to complete the installation, then close this dialog box.

Scrivere codice per ricevere messaggiWrite some code to receive messages

  1. Sostituire le istruzioni using esistenti all'inizio del file Program.cs con le istruzioni using seguenti:Replace the existing using statements at the top of the Program.cs file with the following using statements:

    using System;
    using System.IO;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Azure.Relay;
    
  2. Aggiungere costanti alla classe Program per i dettagli della connessione ibrida.Add constants to the Program class for the hybrid connection details. Sostituire i segnaposto tra parentesi con i valori ottenuti durante la creazione della connessione ibrida.Replace the placeholders in brackets with the values you obtained when creating the hybrid connection. Usare il nome completo dello spazio dei nomi:Be sure to use the fully qualified namespace name:

    private const string RelayNamespace = "{RelayNamespace}.servicebus.windows.net";
    private const string ConnectionName = "{HybridConnectionName}";
    private const string KeyName = "{SASKeyName}";
    private const string Key = "{SASKey}";
    
  3. Aggiungere il metodo seguente, denominato ProcessMessagesOnConnection, alla classe Program:Add the following method called ProcessMessagesOnConnection to the Program class:

    // Method is used to initiate connection
    private static async void ProcessMessagesOnConnection(HybridConnectionStream relayConnection, CancellationTokenSource cts)
    {
        Console.WriteLine("New session");
    
        // The connection is a fully bidrectional stream. 
        // We put a stream reader and a stream writer over it 
        // which allows us 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, we will signal that 
                    // we will no longer send data on this connection
                    // and then break out of the processing loop.
                    await relayConnection.ShutdownAsync(cts.Token);
                    break;
                }
    
                // Output the line on the console
                Console.WriteLine(line);
    
                // Write the line back to the client, prepending "Echo:"
                await writer.WriteLineAsync($"Echo: {line}");
            }
            catch (IOException)
            {
                // Catch an IO exception that is likely caused because
                // the client disconnected.
                Console.WriteLine("Client closed connection");
                break;
            }
        }
    
        Console.WriteLine("End session");
    
        // Closing the connection
        await relayConnection.CloseAsync(cts.Token);
    }
    
  4. Aggiungere un altro metodo denominato RunAsync alla classe Program, come indicato di seguito:Add another method called RunAsync to the Program class, as follows:

    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 will establish the control channel to
        // the Azure Relay service. The control channel will be continuously 
        // maintained and reestablished when connectivity is disrupted.
        await listener.OpenAsync(cts.Token);
        Console.WriteLine("Server listening");
    
        // Providing callback for 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 will allow a clean exit with 
        // this method returning null
        while (true)
        {
            var relayConnection = await listener.AcceptConnectionAsync();
            if (relayConnection == null)
            {
                break;
            }
    
            ProcessMessagesOnConnection(relayConnection, cts);
        }
    
        // Close the listener after we exit the processing loop
        await listener.CloseAsync(cts.Token);
    }
    
  5. Aggiungere la riga di codice seguente al metodo Main nella classe Program:Add the following line of code to the Main method in the Program class:

    RunAsync().GetAwaiter().GetResult();
    

    Al termine, il file Program.cs avrà l'aspetto seguente:Here is what your completed Program.cs file should look like:

    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 will establish the control channel to
                // the Azure Relay service. The control channel will be continuously 
                // maintained and reestablished when connectivity is disrupted.
                await listener.OpenAsync(cts.Token);
                Console.WriteLine("Server listening");
    
                // Providing callback for 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 will allow a clean exit with 
                // this method returning null
                while (true)
                {
                    var relayConnection = await listener.AcceptConnectionAsync();
                    if (relayConnection == null)
                    {
                        break;
                    }
    
                    ProcessMessagesOnConnection(relayConnection, cts);
                }
    
                // Close the listener after we 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. 
                // We put a stream reader and a stream writer over it 
                // which allows us 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, we will signal that 
                            // we will no longer send data on this connection
                            // and then break out of the processing loop.
                            await relayConnection.ShutdownAsync(cts.Token);
                            break;
                        }
    
                        // Output the line on the console
                        Console.WriteLine(line);
    
                        // Write the line back to the client, prepending "Echo:"
                        await writer.WriteLineAsync($"Echo: {line}");
                    }
                    catch (IOException)
                    {
                        // Catch an IO exception that is likely caused because
                        // the client disconnected.
                        Console.WriteLine("Client closed connection");
                        break;
                    }
                }
    
                Console.WriteLine("End session");
    
                // Closing the connection
                await relayConnection.CloseAsync(cts.Token);
            }
        }
    }
    

4. Creare un'applicazione client (mittente)4. Create a client application (sender)

Per inviare messaggi all'inoltro, si scriverà un'applicazione console C# in Visual Studio.To send messages to the Relay, we will write a C# console application using Visual Studio.

Creare un'applicazione consoleCreate a console application

Avviare Visual Studio e creare un nuovo progetto App console (.NET Framework).First, launch Visual Studio and create a new Console App (.NET Framework) project.

Aggiungere il pacchetto NuGet di inoltroAdd the Relay NuGet package

  1. Fare clic con il pulsante destro del mouse sul progetto appena creato e scegliere Gestisci pacchetti NuGet.Right-click the newly created project and then click Manage NuGet Packages.
  2. Fare clic sulla scheda Sfoglia, quindi cercare "Microsoft.Azure.Relay" e selezionare l'elemento Inoltro di Microsoft Azure.Click the Browse tab, then search for "Microsoft.Azure.Relay" and select the Microsoft Azure Relay item. Fare clic su Installa per completare l'installazione, quindi chiudere questa finestra di dialogo.Click Install to complete the installation, then close this dialog box.

Scrivere codice per inviare messaggiWrite some code to send messages

  1. Sostituire le istruzioni using esistenti all'inizio del file Program.cs con le istruzioni using seguenti:Replace the existing using statements at the top of the Program.cs file with the following using statements:

    using System;
    using System.IO;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Azure.Relay;
    
  2. Aggiungere costanti alla classe Program per i dettagli della connessione ibrida.Add constants to the Program class for the hybrid connection details. Sostituire i segnaposto tra parentesi con i valori ottenuti durante la creazione della connessione ibrida.Replace the placeholders in brackets with the values you obtained when creating the hybrid connection. Usare il nome completo dello spazio dei nomi:Be sure to use the fully qualified namespace name:

    private const string RelayNamespace = "{RelayNamespace}.servicebus.windows.net";
    private const string ConnectionName = "{HybridConnectionName}";
    private const string KeyName = "{SASKeyName}";
    private const string Key = "{SASKey}";
    
  3. Aggiungere il metodo seguente alla classe Program:Add the following method to the Program class:

    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();
    
        // We 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 will shut down the write task after 
        // sending it to the server. The server will then cleanly shut down
        // the connection which will terminate 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, we 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 form the console
                string line = await reader.ReadLineAsync();
                // Write the line out, also when it's empty
                await writer.WriteLineAsync(line);
                // Quit when the line was empty
                if (String.IsNullOrEmpty(line))
                    break;
            }
            while (true);
        });
    
        // Wait for both tasks to complete
        await Task.WhenAll(reads, writes);
        await relayConnection.CloseAsync(CancellationToken.None);
    }
    
  4. Aggiungere la riga di codice seguente al metodo Main nella classe Program.Add the following line of code to the Main method in the Program class.

    RunAsync().GetAwaiter().GetResult();
    

    Ecco l'aspetto che avrà il file Program.cs.Here is what your Program.cs should look like.

    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();
    
                // We run two conucrrent 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 will shut down the write task after 
                // sending it to the server. The server will then cleanly shut down
                // the connection which will terminate 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, we 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 form the console
                        string line = await reader.ReadLineAsync();
                        // Write the line out, also when it's empty
                        await writer.WriteLineAsync(line);
                        // Quit when the line was empty
                        if (String.IsNullOrEmpty(line))
                            break;
                    }
                    while (true);
                });
    
                // Wait for both tasks to complete
                await Task.WhenAll(reads, writes);
                await relayConnection.CloseAsync(CancellationToken.None);
            }
        }
    }
    

5. Eseguire le applicazioni5. Run the applications

  1. Eseguire l'applicazione server.Run the server application.
  2. Eseguire l'applicazione client e immettere il testo.Run the client application and enter some text.
  3. Assicurarsi che la console dell'applicazione server restituisca il testo immesso nell'applicazione client.Ensure that the server application console outputs the text that was entered in the client application.

applicazioni in esecuzione

A questo punto è stata creata un'applicazione per le connessioni ibride end-to-end.Congratulations, you have created an end-to-end Hybrid Connections application.

Passaggi successivi:Next steps: