Erste Schritte mit WebSockets von Relay Hybrid Connections in .NET

In dieser Schnellstartanleitung erstellen Sie Sender- und Empfängeranwendungen in .NET, die mithilfe von Hybrid Connections WebSockets in Azure Relay Nachrichten senden und empfangen. Allgemeine Informationen zu Azure Relay finden Sie unter Was ist Azure Relay?.

Diese Schnellstartanleitung umfasst folgende Schritte:

  1. Erstellen eines Relay-Namespace über das Azure-Portal
  2. Erstellen einer Hybridverbindung in diesem Namespace über das Azure-Portal
  3. Erstellen einer Serverkonsolenanwendung (Listener) zum Empfangen von Nachrichten
  4. Erstellen einer Clientkonsolenanwendung (Absender) zum Senden von Nachrichten
  5. Ausführen von Anwendungen

Voraussetzungen

Zum Durchführen dieses Tutorials benötigen Sie Folgendes:

  • Visual Studio 2015 oder eine höhere Version. Für die Beispiele in diesem Tutorial wird Visual Studio 2017 verwendet.
  • Ein Azure-Abonnement. Falls Sie kein Abonnement besitzen, können Sie ein kostenloses Konto erstellen, bevor Sie beginnen.

Erstellen eines Namespace

  1. Melden Sie sich beim Azure-Portal an.

  2. Wählen Sie im Menü links Alle Dienste aus. Wählen Sie Integration aus, suchen Sie nach Relays, zeigen Sie mit der Maus auf Relays, und wählen Sie dann Erstellen.

    Screenshot showing the selection of Relays -> Create button.

  3. Führen Sie die folgenden Schritte auf der Seite Namespace erstellen aus:

    1. Wählen Sie ein Azure-Abonnement aus, in dem der Namespace erstellt werden soll.

    2. Wählen Sie unter Ressourcengruppe eine vorhandene Ressourcengruppe aus, in der der Namespace platziert werden soll, oder erstellen Sie eine neue Ressourcengruppe.

    3. Geben Sie einen Namen für den Relay-Namespace ein.

    4. Wählen Sie die Region aus, in dem bzw. in der Ihr Namespace gehostet werden soll.

    5. Wählen Sie am unteren Rand der Seite die Option Bewerten + erstellen aus.

      Screenshot showing the Create namespace page.

    6. Wählen Sie auf der Seite Überprüfen + erstellen die Option Erstellen aus.

    7. Nach ein paar Minuten sehen Sie die Seite Vermittlung für den Namespace.

      Screenshot showing the home page for Relay namespace.

Abrufen von Anmeldeinformationen für die Verwaltung

  1. Wählen Sie auf der Seite Vermittlung die Option Freigegebene Zugriffsrichtlinien im linken Menü aus. `

  2. Wählen Sie auf der Seite Freigegebene Zugriffsrichtlinien die Option RootManageSharedAccessKey aus.

  3. Klicken Sie unter SAS-Richtlinie: RootManageSharedAccessKey neben Primäre Verbindungszeichenfolge auf die Schaltfläche Kopieren. Dadurch wird die Verbindungszeichenfolge zur späteren Verwendung in die Zwischenablage kopiert. Fügen Sie diesen Wert in den Editor oder an einem anderen temporären Speicherort ein.

  4. Wiederholen Sie den vorherigen Schritt, um den Wert von Primärschlüssel zu kopieren und zur späteren Verwendung an einem temporären Speicherort einzufügen.

    Screenshot showing the connection info for Relay namespace.

Hybridverbindung erstellen

Führen Sie auf der Relayseite für Ihren Namespace die folgenden Schritte aus, um eine Hybridverbindung zu erstellen.

  1. Wählen Sie im linken Menü unter Entitäten die Option Hybridverbindungen und dann + Hybridverbindung aus.

    Screenshot showing the Hybrid Connections page.

  2. Geben Sie auf der Seite Hybridverbindung erstellen einen Namen für die Hybridverbindung ein, und wählen Sie dann Erstellen aus.

    Screenshot showing the Create Hybrid Connection page.

Erstellen einer Serveranwendung (Listener)

Schreiben Sie in Visual Studio eine C#-Konsolenanwendung, um auf Nachrichten des Relays zu lauschen und sie zu empfangen.

Erstellen einer Konsolenanwendung

Erstellen Sie in Visual Studio ein neues Projekt vom Typ Konsolen-App (.NET Framework).

Hinzufügen des Relay-NuGet-Pakets

  1. Klicken Sie mit der rechten Maustaste auf das neu erstellte Projekt, und wählen Sie NuGet-Pakete verwalten aus.
  2. Klicken Sie auf Durchsuchen, und suchen Sie nach Microsoft.Azure.Relay. Klicken Sie in den Suchergebnissen auf Microsoft Azure-Relay.
  3. Klicken Sie auf Installieren, um die Installation abzuschließen. Schließen Sie das Dialogfeld.

Schreiben von Code zum Empfangen von Nachrichten

  1. Ersetzen Sie die vorhandenen using-Anweisungen am Anfang der Datei „Program.cs“ durch die folgenden using-Anweisungen:

    using System;
    using System.IO;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Net;
    using Microsoft.Azure.Relay;
    
  2. Fügen Sie der Program-Klasse Konstanten als Hybridverbindungsdetails hinzu. Ersetzen Sie die Platzhalter durch die Werte, die beim Erstellen der Hybridverbindung abgerufen wurden. Verwenden Sie den vollqualifizierten Namespacenamen.

    // 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";
    
  3. Fügen Sie der Klasse Program die Methode ProcessMessagesOnConnection hinzu:

    // 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);
    }
    
  4. Fügen Sie der Klasse Program die Methode RunAsync hinzu:

    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);
    }
    
  5. Fügen Sie der Main-Methode in der Program-Klasse die folgende Codezeile hinzu:

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

    Die fertige Datei „Program.cs“ sollte wie folgt aussehen:

    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);
            }
        }
    }
    

Erstellen einer Clientanwendung (Absender)

Schreiben Sie in Visual Studio eine C#-Konsolenanwendung, um Nachrichten an das Relay zu senden.

Erstellen einer Konsolenanwendung

Erstellen Sie in Visual Studio ein neues Projekt vom Typ Konsolen-App (.NET Framework).

Hinzufügen des Relay-NuGet-Pakets

  1. Klicken Sie mit der rechten Maustaste auf das neu erstellte Projekt, und wählen Sie NuGet-Pakete verwalten aus.
  2. Klicken Sie auf Durchsuchen, und suchen Sie nach Microsoft.Azure.Relay. Klicken Sie in den Suchergebnissen auf Microsoft Azure-Relay.
  3. Klicken Sie auf Installieren, um die Installation abzuschließen. Schließen Sie das Dialogfeld.

Schreiben von Code zum Senden von Nachrichten

  1. Ersetzen Sie die vorhandenen using-Anweisungen am Anfang der Datei „Program.cs“ durch die folgenden using-Anweisungen:

    using System;
    using System.IO;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Azure.Relay;
    
  2. Fügen Sie der Program-Klasse Konstanten als Hybridverbindungsdetails hinzu. Ersetzen Sie die Platzhalter durch die Werte, die beim Erstellen der Hybridverbindung abgerufen wurden. Verwenden Sie den vollqualifizierten Namespacenamen.

    // 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";
    
  3. Fügen Sie der Program-Klasse die folgende Methode hinzu:

    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);
    }
    
  4. Fügen Sie der Main-Methode in der Program-Klasse die folgende Codezeile hinzu.

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

    Die Datei „Program.cs“ sollte wie folgt aussehen:

    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);
            }
        }
    }
    

Ausführen der Anwendungen

  1. Führen Sie die Serveranwendung aus.

  2. Führen Sie die Clientanwendung aus, und geben Sie Text ein.

  3. Vergewissern Sie sich, dass in der Konsole der Serveranwendung der Text angezeigt wird, der in die Clientanwendung eingegeben wurde.

    Console windows testing both the server and client applications.

Glückwunsch! Sie haben eine vollständige Hybrid Connections-Anwendung erstellt!

Nächste Schritte

In dieser Schnellstartanleitung haben Sie Client- und Serveranwendungen in .NET erstellt, die mithilfe von WebSockets Nachrichten senden und empfangen. Das Hybrid Connections-Feature von Azure Relay unterstützt auch die Verwendung von HTTP zum Senden und Empfangen von Nachrichten. Informationen zur Verwendung von HTTP mit Hybrid Connections von Azure Relay finden Sie unter Erste Schritte mit HTTP-Anforderungen von Relay Hybrid Connections in .NET.

In dieser Schnellstartanleitung haben Sie .NET Framework zum Erstellen von Client- und Serveranwendungen verwendet. Informationen zum Schreiben von Client- und Serveranwendungen mithilfe von Node.js finden Sie unter Erste Schritte mit WebSockets von Relay Hybrid Connections in Node oder Erste Schritte mit HTTP-Anforderungen von Relay Hybrid Connections in .NET.