開始使用 .NET 中的轉送混合式連線ions WebSocket
在本快速入門中,您會使用 Azure 轉送中的混合式 連線ions WebSocket 建立 .NET 傳送者和接收者應用程式,以傳送和接收訊息。 若要瞭解 Azure 轉寄一般,請參閱 Azure 轉寄 。
在本快速入門中,您會採取下列步驟:
- 使用 Azure 入口網站 建立轉寄命名空間。
- 使用 Azure 入口網站,在該命名空間中建立混合式連線。
- 撰寫伺服器(接聽程式)主控台應用程式以接收訊息。
- 撰寫用戶端 (sender) 主控台應用程式以傳送訊息。
- 執行應用程式。
必要條件
若要完成本教學課程,您需要下列必要條件:
- Visual Studio 2015 或更新版本。 本教學課程中的範例使用 Visual Studio 2017。
- Azure 訂用帳戶。 如果您沒有 Azure 訂用帳戶,請在開始前建立免費帳戶。
建立命名空間
登入 Azure 入口網站。
選取 左側功能表上的 [所有服務 ]。 依序選取 [整合 ]、搜尋 [轉寄]、將滑鼠移至 [轉寄 ] 上方 ,然後選取 [ 建立 ]。
在 [ 建立命名空間] 頁面上,遵循下列步驟:
選擇要在其中建立命名空間的 Azure 訂用帳戶。
針對 [ 資源群組 ],選擇要放置命名空間的現有資源群組,或建立新的資源群組。
輸入轉寄命名空間的名稱。
選取您的命名空間應該裝載所在的區域。
選取頁面底部的 [檢閱 + 建立] 。
在 [檢閱 + 建立] 頁面上,選取 [建立]。
幾分鐘後,您會看到 命名空間的 [轉寄 ] 頁面。
取得管理認證
在 [ 轉寄 ] 頁面上,選取 左側功能表上的 [共用存取原則 ]。 `
在 [ 共用存取原則] 頁面上,選取 [RootManageSharedAccessKey ]。
在 [SAS 原則:RootManageSharedAccessKey] 下 ,選取 [主要連線ion String 旁的 [複製 ] 按鈕。 此動作會將連接字串複製到剪貼簿以供稍後使用。 將此值貼到記事本或其他一些暫存位置。
重複上述步驟,將 [主要金鑰 ] 的值 複製並貼到暫存位置,以供日後使用。
建立混合式連線
在命名空間的 [ 轉送 ] 頁面上,遵循下列步驟來建立混合式連線。
在左側功能表上的 [實體 ] 下 ,選取 [混合式連線] ,然後選取 [+ 混合式連線]。
在 [ 建立混合式連線ion ] 頁面上,輸入混合式連線的名稱,然後選取 [ 建立 ]。
建立伺服器應用程式 (接聽程式)
在 Visual Studio 中,撰寫 C# 主控台應用程式以接聽和接收來自轉播的訊息。
建立主控台應用程式
在 Visual Studio 中,建立新的 主控台應用程式 (.NET Framework) 專案。
新增轉寄 NuGet 套件
- 以滑鼠右鍵按一下新建立的專案,然後選取 [ 管理 NuGet 套件 ]。
- 選取 [ 流覽 ],然後搜尋 Microsoft.Azure.Relay 。 在搜尋結果中,選取 [Microsoft Azure 轉寄 ]。
- 選取 [ 安裝 ] 以完成安裝。 關閉對話方塊。
撰寫程式碼以接收訊息
在 Program.cs 檔案頂端,將現有的
using
語句取代為下列using
語句:using System; using System.IO; using System.Threading; using System.Threading.Tasks; using System.Net; using Microsoft.Azure.Relay;
將常數新增至
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";
將
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); }
將
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); }
將下列程式程式碼新增至
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 套件
- 以滑鼠右鍵按一下新建立的專案,然後選取 [ 管理 NuGet 套件 ]。
- 選取 [ 流覽 ],然後搜尋 Microsoft.Azure.Relay 。 在搜尋結果中,選取 [Microsoft Azure 轉寄 ]。
- 選取 [ 安裝 ] 以完成安裝。 關閉對話方塊。
撰寫程式碼以傳送訊息
在 Program.cs 檔案頂端,將現有的
using
語句取代為下列using
語句:using System; using System.IO; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Relay;
將常數新增至
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";
將下列方法新增至
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); }
將下列程式程式碼新增至
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); } } }
執行應用程式
執行伺服器應用程式。
執行用戶端應用程式並輸入一些文字。
確定伺服器應用程式主控台會顯示在用戶端應用程式中輸入的文字。
恭喜您,您已建立完整的混合式連線ions 應用程式!
下一步
在本快速入門中,您已建立使用 WebSocket 來傳送和接收訊息的 .NET 用戶端和伺服器應用程式。 Azure 轉送的混合式連線功能也支援使用 HTTP 來傳送和接收訊息。 若要瞭解如何搭配 Azure 轉送混合式連線使用 HTTP,請參閱 HTTP 快速入門 。
在本快速入門中,您已使用 .NET Framework 來建立用戶端和伺服器應用程式。 若要瞭解如何使用 Node.js 撰寫用戶端和伺服器應用程式,請參閱 Node.js WebSockets 快速入門 或 Node.js HTTP 快速入門 。