Поделиться через


Начало работы с гибридными подключениями Azure Relay с использованием WebSocket и .NET

В этом кратком руководстве описано, как создать приложения .NET, которые отправляют и получают сообщения с использованием гибридных подключений по протоколу WebSocket в Azure Relay. См. дополнительные сведения о службе Azure Relay.

При работе с этим кратким руководством вы выполните следующие задачи:

  1. Создайте пространство имен ретранслятора с помощью портала Azure.
  2. Создайте гибридное подключение в этом пространстве имен с помощью портала Azure.
  3. Создайте серверное консольное приложение (прослушиватель) для получения сообщений.
  4. Создайте клиентское консольное приложение (отправитель) для отправки сообщений.
  5. Запустите приложения.

Необходимые компоненты

Для работы с данным руководством вам потребуется:

  • Visual Studio 2015 или более поздней версии. В описанных в этом руководстве примерах используется Visual Studio 2017.
  • Подписка Azure. Если у вас еще нет подписки Azure, создайте бесплатную учетную запись, прежде чем начать работу.

Создание пространства имен

  1. Войдите на портал Azure.

  2. В меню слева выберите Все службы. Выберите "Интеграция", найдите ретрансляторы, переместите указатель мыши на ретрансляторы и нажмите кнопку "Создать".

    Снимок экрана: выбор ретрансляторов —> кнопка

  3. На странице "Создание пространства имен" выполните следующие действия.

    1. Выберите подписку Azure, в которой будет создано пространство имен.

    2. Выберите существующую группу ресурсов, в которую будет размещено это пространство имен, или создайте новую.

    3. Введите имя пространства имен Ретранслятора.

    4. Выберите регион, в котором должно размещаться пространство имен.

    5. В нижней части страницы выберите Review + create (Проверить и создать).

      Снимок экрана: страница

    6. На странице Отзыв и создание выберите Создать.

    7. Через несколько минут вы увидите страницу Ретранслятора для пространства имен.

      Снимок экрана: домашняя страница пространства имен Ретранслятора.

Получение учетных данных управления

  1. На странице "Ретранслятор" выберите политики общего доступа в меню слева. `

  2. На странице Политики общего доступа щелкните RootManageSharedAccessKey.

  3. В разделе SAS Policy: RootManageSharedAccessKey (Политика SAS: RootManageSharedAccessKey) нажмите кнопку Копировать рядом с элементом Первичная строка подключения. Строка подключения будет скопирована в буфер обмена для дальнейшего использования. Вставьте на время эти значения в Блокноте или любом другом месте.

  4. Повторите предыдущий шаг, скопировав и вставив значение первичного ключа во временное расположение для последующего использования.

    Снимок экрана: сведения о подключении для пространства имен Ретранслятора.

Создание гибридного подключения

На странице Ретранслятора для пространства имен выполните следующие действия, чтобы создать гибридное подключение.

  1. В меню слева выберите "Гибридные подключения" и выберите "Гибридные подключения".

    Снимок экрана: страница гибридных подключений.

  2. На странице "Создание гибридного подключения" введите имя гибридного подключения и нажмите кнопку "Создать".

    Снимок экрана: страница

Создание серверного приложения (прослушивателя)

Создайте в Visual Studio консольное приложение C# для прослушивания и получения сообщений, отправленных ретранслятором.

Создание консольного приложение

В Visual Studio создайте проект Консольное приложение (.NET Framework).

Добавление пакета ретранслятора NuGet

  1. Щелкните созданный проект правой кнопкой мыши и выберите Управление пакетами NuGet.
  2. Выберите Обзор и выполните поиск по ключевой фразе Microsoft.Azure.Relay. В результатах поиска выберите Ретранслятор Microsoft Azure.
  3. Выберите Установить для завершения установки. Закройте диалоговое окно.

Написание кода для получения сообщений

  1. В начале файла Program.cs замените существующие операторы using следующими операторами using:

    using System;
    using System.IO;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Net;
    using Microsoft.Azure.Relay;
    
  2. Добавьте константы в класс Program, чтобы получить сведения о гибридном подключении. Замените заполнители значениями, полученными при создании гибридного подключения. Необходимо использовать полное имя пространства имен.

    // 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. Добавьте метод ProcessMessagesOnConnection в класс Program:

    // 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. Добавьте метод RunAsync в класс Program:

    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. В метод Main в классе Program добавьте следующую строку кода:

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

    Готовый файл Program.cs будет выглядеть так:

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

Создание клиентского приложения (отправителя)

Создайте в Visual Studio консольное приложение C# для отправки сообщений в ретранслятор.

Создание консольного приложение

В Visual Studio создайте проект Консольное приложение (.NET Framework).

Добавление пакета ретранслятора NuGet

  1. Щелкните созданный проект правой кнопкой мыши и выберите Управление пакетами NuGet.
  2. Выберите Обзор и выполните поиск по ключевой фразе Microsoft.Azure.Relay. В результатах поиска выберите Ретранслятор Microsoft Azure.
  3. Выберите Установить для завершения установки. Закройте диалоговое окно.

Написание кода для отправки сообщений

  1. В начале файла Program.cs замените существующие операторы using следующими операторами using:

    using System;
    using System.IO;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Azure.Relay;
    
  2. Добавьте константы в класс Program, чтобы получить сведения о гибридном подключении. Замените заполнители значениями, полученными при создании гибридного подключения. Необходимо использовать полное имя пространства имен.

    // 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. Добавьте приведенный ниже метод в класс 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);
    }
    
  4. В метод Main в классе Program добавьте следующую строку кода.

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

    Файл Program.cs должен выглядеть следующим образом:

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

Примечание.

Пример кода в этой статье использует строка подключения для проверки подлинности в пространстве имен Ретранслятора Azure, чтобы упростить учебник. Мы рекомендуем использовать проверку подлинности Идентификатора Microsoft Entra в рабочих средах, а не использовать строка подключения или подписанные URL-адреса, что может быть проще скомпрометировано. Подробные сведения и пример кода для использования проверки подлинности идентификатора Microsoft Entra см. в статье "Проверка подлинности и авторизация приложения с помощью идентификатора Microsoft Entra ID" для доступа к сущностям Ретрансляции Azure и аутентификации управляемого удостоверения с помощью идентификатора Microsoft Entra для доступа к ресурсам Ретранслятора Azure.

Запуск приложений

  1. Запустите серверное приложение.

  2. Запустите клиентское приложение и введите любой текст.

  3. Убедитесь, что в серверном консольном приложении отображается текст, введенный в клиентском приложении.

    Окна консоли для тестирования серверного и клиентского приложений.

Поздравляем, вы создали готовое приложение для гибридных подключений!

Следующие шаги

В этом кратком руководстве описано, как создать клиентские и серверные приложения .NET, которые отправляют и получают сообщения по протоколу WebSocket. Функция гибридных подключений службы Azure Relay также поддерживает использование протокола HTTP для отправки и получения сообщений. См. дополнительные сведения об использовании протокола HTTP с гибридными подключениями Azure Relay.

В этом кратком руководстве описано, как использовать .NET Framework для создания клиентских и серверных приложений. Сведения о том, как создавать клиентские и серверные приложения с помощью Node.js, см. в руководствах по использованию Node.js и WebSocket или Node.js и HTTP.