Introducción a WebSockets de Conexiones híbridas de Relay en .NET
En esta guía de inicio rápido, va a crear aplicaciones de remitente y receptor de .NET que envían y reciben mensajes mediante WebSockets de Conexiones híbridas en Azure Relay. Para información acerca de Azure Relay en general, consulte Azure Relay.
En esta guía de inicio rápido, realizará los siguientes pasos:
- Creación de un espacio de nombres de Relay mediante Azure Portal.
- Creación de una conexión híbrida en dicho espacio de nombres mediante Azure Portal.
- Escritura de una aplicación de consola de servidor (de escucha) para recibir mensajes.
- Escritura de una aplicación de consola de cliente (remitente) para enviar mensajes.
- Ejecución de aplicaciones.
Requisitos previos
Para completar este tutorial, debe cumplir los siguientes requisitos previos:
- Visual Studio 2015 o posterior. En los ejemplos de este tutorial se usa Visual Studio 2017.
- Suscripción a Azure. Si no tiene una, cree una cuenta gratuita antes de empezar.
Creación de un espacio de nombres
Inicie sesión en Azure Portal.
Seleccione Todos los servicios en el menú de la izquierda. Seleccione Integración, busque Retransmisiones, mueva el mouse sobre Retransmisiones y, a continuación, seleccione Crear.
En la página Crear espacio de nombres, siga estos pasos:
Elija la suscripción de Azure en la que se va a crear el espacio de nombres.
En Grupo de recursos, elija un grupo de recursos existente en el que se colocará el espacio de nombres o cree uno.
Escriba un nombre para el espacio de nombres de Retransmisión.
Seleccione la región donde se debe hospedar el espacio de nombres.
En la parte inferior de la página, seleccione Revisar y crear.
En la página Revisar y crear, seleccione Crear.
Al cabo de unos minutos, verá la página Retransmisión del espacio de nombres.
Obtención de las credenciales de administración
En la página Retransmisión, seleccione Directivas de acceso compartido en el menú de la izquierda. `
En la página Directivas de acceso compartido, seleccione RootManageSharedAccessKey.
En Directiva SAS: RootManageSharedAccessKey, haga clic en el botón Copiar situado junto a Cadena de conexión principal. Esta acción copia la cadena de conexión en el Portapapeles para su uso posterior. Pegue este valor en el Bloc de notas o cualquier otra ubicación temporal.
Repita el paso anterior para copiar y pegar el valor de Clave principal en una ubicación temporal para su uso posterior.
Create a hybrid connection
En la página Relay del espacio de nombres, siga estos pasos para crear una conexión híbrida.
En el menú de la izquierda, en Entidades, seleccione Conexiones híbridas y, después, + Conexión híbrida.
En la página Crear conexión híbrida, escriba un nombre para la conexión híbrida y seleccione Crear.
Creación de una aplicación de servidor (agente de escucha)
En Visual Studio, escriba una aplicación de consola en C# para escuchar y recibir mensajes de Relay.
Creación de una aplicación de consola
En Visual Studio, cree un nuevo proyecto de Aplicación de consola (.NET Framework).
Adición del paquete Relay NuGet
- Haga clic con el botón derecho en el proyecto recién creado y seleccione Administrar paquetes NuGet.
- Seleccione Examinar y, a continuación, busque Microsoft.Azure.Relay. En los resultados de la búsqueda, seleccione Microsoft Azure Relay.
- Seleccione Instalar para completar la instalación. Cerrar el cuadro de diálogo.
Escritura de código para recibir mensajes
En la parte superior del archivo Program.cs, reemplace las instrucciones
using
existentes por las siguientes instruccionesusing
:using System; using System.IO; using System.Threading; using System.Threading.Tasks; using System.Net; using Microsoft.Azure.Relay;
Agregue constantes a la clase
Program
para los detalles de la conexión híbrida. Reemplace los marcadores de posición por los valores que obtuvo al crear la conexión híbrida. Asegúrese de utilizar el nombre de espacio de nombres completo.// 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";
Agregue el método
ProcessMessagesOnConnection
a la claseProgram
:// 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); }
Agregue el método
RunAsync
a la claseProgram
: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); }
Agregue la siguiente línea de código al método
Main
de la claseProgram
:RunAsync().GetAwaiter().GetResult();
Este es el aspecto que debería tener el archivo Program.cs completado:
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); } } }
Creación de una aplicación de cliente (remitente)
En Visual Studio, escriba una aplicación de consola en C# para enviar mensajes a Relay.
Creación de una aplicación de consola
En Visual Studio, cree un nuevo proyecto de Aplicación de consola (.NET Framework).
Adición del paquete Relay NuGet
- Haga clic con el botón derecho en el proyecto recién creado y seleccione Administrar paquetes NuGet.
- Seleccione Examinar y, a continuación, busque Microsoft.Azure.Relay. En los resultados de la búsqueda, seleccione Microsoft Azure Relay.
- Seleccione Instalar para completar la instalación. Cerrar el cuadro de diálogo.
Escritura de código para enviar mensajes
En la parte superior del archivo Program.cs, reemplace las instrucciones
using
existentes por las siguientes instruccionesusing
:using System; using System.IO; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Relay;
Agregue constantes a la clase
Program
para los detalles de la conexión híbrida. Reemplace los marcadores de posición por los valores que obtuvo al crear la conexión híbrida. Asegúrese de utilizar el nombre de espacio de nombres completo.// 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";
Agregue el siguiente método a la clase
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); }
Agregue la siguiente línea de código al método
Main
de la claseProgram
.RunAsync().GetAwaiter().GetResult();
El archivo Program.cs debería tener el siguiente aspecto:
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:
El código de ejemplo de este artículo usa una cadena de conexión para autenticarse en un espacio de nombres de Azure Relay para simplificar el tutorial. Se recomienda usar la autenticación de Microsoft Entra ID en entornos de producción, en lugar de usar cadenas de conexión o firmas de acceso compartido, lo que puede verse más fácilmente en peligro. Para obtener información detallada y código de ejemplo para usar la autenticación de Microsoft Entra ID, consulte Autenticación y autorización de una aplicación con el Microsoft Entra ID para acceder a las entidades de Azure Relay y Autenticar una identidad administrada con Microsoft Entra ID para acceder a los recursos de Azure Relay.
Ejecución de las aplicaciones
Ejecute la aplicación de servidor.
Ejecute la aplicación de cliente y escriba algún texto.
Asegúrese de que la consola de aplicación de servidor muestra el texto que se escribió en la aplicación cliente.
Enhorabuena, ha creado una aplicación de Conexiones híbridas completa.
Pasos siguientes
En esta guía de inicio rápido, ha creado aplicaciones de cliente y servidor de .NET que han usado WebSockets para enviar y recibir mensajes. La característica Conexiones híbridas de Azure Relay también admite el uso de HTTP para enviar y recibir mensajes. Para aprender a usar HTTP con Conexiones híbridas de Azure Relay, consulte la guía de inicio rápido de HTTP.
En esta guía de inicio rápido ha usado .NET Framework para crear aplicaciones cliente y servidor. Para aprender a escribir aplicaciones cliente y servidor con Node.js, consulte la Guía de inicio rápido de WebSockets en Node.js o la Guía de inicio rápido de HTTP para Node.js.