必要條件
本教學課程假設您已熟悉如何編寫及執行 Fuchsia 並實作 FIDL 伺服器,兩者都包含在 FIDL 伺服器教學課程。如需完整的 FIDL 教學課程,請參閱 總覽。
總覽
本教學課程將實作 FIDL 通訊協定的用戶端並執行 針對上一個教學課程中建立的伺服器執行測試。這個架構中的用戶端 教學課程是同步性的我們也提供替代的教學課程 非同步用戶端。
若您想要自行編寫程式碼,請刪除下列目錄:
rm -r examples/fidl/rust/client_sync/*
建立元件
在 examples/fidl/rust/client_sync
建立新的元件專案:
將
main()
函式新增至examples/fidl/rust/client_sync/src/main.rs
:fn main() { println!("Hello, world!"); }
在
examples/fidl/rust/client_sync/BUILD.gn
中宣告用戶端的目標:import("//build/components.gni") import("//build/rust/rustc_binary.gni") # Declare an executable for the client. rustc_binary("bin") { name = "fidl_echo_rust_client_sync" edition = "2021" sources = [ "src/main.rs" ] } fuchsia_component("echo-client") { component_name = "echo_client" manifest = "meta/client.cml" deps = [ ":bin" ] }
在
examples/fidl/rust/client_sync/meta/client.cml
中新增元件資訊清單:{ include: [ "syslog/client.shard.cml" ], // Information about the program to run. program: { // Use the built-in ELF runner. runner: "elf", // The binary to run for this component. binary: "bin/fidl_echo_rust_client_sync", }, // Capabilities used by this component. use: [ { protocol: "fuchsia.examples.Echo" }, ], }
建立元件後,請確定能將其新增至 建構設定:
fx set core.x64 --with //examples/fidl/rust/client_sync:echo-client
建構 Fuchsia 映像檔:
fx build
編輯 GN 依附元件
將下列依附元件新增至
rustc_binary
:deps = [ "//examples/fidl/fuchsia.examples:fuchsia.examples_rust", "//src/lib/fuchsia-component", "//src/lib/zircon/rust:fuchsia-zircon", "//third_party/rust_crates:anyhow", ]
然後在
main.rs
中匯入:use anyhow::{Context as _, Error}; use fidl_fuchsia_examples::{EchoEvent, EchoMarker}; use fuchsia_component::client::connect_to_protocol_sync; use fuchsia_zircon as zx;
如要瞭解這些依附元件,請參閱伺服器教學課程。
新的依附元件是 fuchsia-zircon
,這是包含類型安全的 Crate
建立 Zircon 核心系統呼叫的繫結。在此範例中,Crate 的用途是
建立管道。
連線至伺服器
本節中的步驟說明如何在 main()
函式中新增程式碼
這個網路可讓用戶端連上伺服器,並向伺服器發出要求。
初始化管道
fn main() -> Result<(), Error> {
// Connect to the Echo protocol, returning a synchronous proxy
let echo =
connect_to_protocol_sync::<EchoMarker>().context("Failed to connect to echo service")?;
// Make an EchoString request, with no timeout for receiving the response
let res = echo.echo_string("hello", zx::MonotonicTime::INFINITE)?;
println!("response: {:?}", res);
// Make a SendString request
echo.send_string("hi")?;
// Wait for a single OnString event.
let EchoEvent::OnString { response } =
echo.wait_for_event(zx::MonotonicTime::INFINITE).context("error receiving events")?;
println!("Received OnString event for string {:?}", response);
Ok(())
}
這個管道會用來在用戶端和伺服器之間進行通訊。
連線至伺服器
fn main() -> Result<(), Error> {
// Connect to the Echo protocol, returning a synchronous proxy
let echo =
connect_to_protocol_sync::<EchoMarker>().context("Failed to connect to echo service")?;
// Make an EchoString request, with no timeout for receiving the response
let res = echo.echo_string("hello", zx::MonotonicTime::INFINITE)?;
println!("response: {:?}", res);
// Make a SendString request
echo.send_string("hi")?;
// Wait for a single OnString event.
let EchoEvent::OnString { response } =
echo.wait_for_event(zx::MonotonicTime::INFINITE).context("error receiving events")?;
println!("Received OnString event for string {:?}", response);
Ok(())
}
connect_channel_to_service
會將提供的管道繫結至指定結尾
課程中也會快速介紹 Memorystore
這是 Google Cloud 的全代管 Redis 服務基本上,這個呼叫會觸發在用戶端上啟動的一系列事件,並透過上一個教學課程的伺服器程式碼進行追蹤:
- 向元件架構提出要求,該架構包含要連線的服務名稱,以及
管道的其他部分服務名稱是使用
SERVICE_NAME
以隱含方式取得EchoMarker
範本引數,這類似於伺服器在伺服器上決定服務路徑的方式 結尾。 - 這個用戶端物件是從
connect_to_protocol
傳回。
在背景中,傳送至元件架構的要求會轉送至伺服器:
- 伺服器程序收到這項要求後,
它會喚醒
async::Executor
執行程式,並通知ServiceFs
工作現在可以 並應該執行 ServiceFs
會喚醒、查看程序啟動控點中的可用要求,以及 在(service_name, service_startup_func)
清單中查詢所要求服務的名稱 透過呼叫add_service
、add_fidl_service
等條件。如果相符的service_name
存在,則會使用提供的管道呼叫service_startup_func
,以連線至新服務。- 系統會使用
RequestStream
呼叫IncomingService::Echo
向add_fidl_service
註冊的Echo
FIDL 通訊協定 (類型管道)。 傳入的要求管道會儲存在IncomingService::Echo
中,並新增至for_each_concurrent
會將ServiceFs
消耗成類型的Stream
IncomingService
。系統會針對串流中的每個項目執行處理常式,以比對傳入 要求及分派給run_echo_server
。每個呼叫所產生的 FutureServiceFs
串流為await
時,會並行執行run_echo_server
。 - 在管道上傳送要求時,系統會可讀取
Echo
服務管道, 會在run_echo_server
主體中喚醒非同步程式碼。
將要求傳送至伺服器
程式碼會向伺服器發出兩項要求:
EchoString
要求SendString
要求
fn main() -> Result<(), Error> {
// Connect to the Echo protocol, returning a synchronous proxy
let echo =
connect_to_protocol_sync::<EchoMarker>().context("Failed to connect to echo service")?;
// Make an EchoString request, with no timeout for receiving the response
let res = echo.echo_string("hello", zx::MonotonicTime::INFINITE)?;
println!("response: {:?}", res);
// Make a SendString request
echo.send_string("hi")?;
// Wait for a single OnString event.
let EchoEvent::OnString { response } =
echo.wait_for_event(zx::MonotonicTime::INFINITE).context("error receiving events")?;
println!("Received OnString event for string {:?}", response);
Ok(())
}
收到伺服器的回應之前,echo_string
的呼叫會遭到封鎖,因此
並將逾時引數做為最後一個參數
另一方面,對 send_string
的呼叫自 SendString
起沒有逾時參數
沒有回應。在目前的伺服器實作中的情況下,OnString
事件
收到這項要求後,就會傳送給用戶端。不過,同步的 Rust 繫結機制不會改變
不支援處理事件。
繫結參考資料說明這些方法的產生方式,以及 Fuchsia rustdoc 提供所產生 FIDL Crate 的說明文件。
執行用戶端
為了讓用戶端和伺服器使用 Echo
通訊協定進行通訊,
元件架構必須從 fuchsia.examples.Echo
伺服器傳送至用戶端在本教學課程中
運作範圍
元件是
來宣告適當的功能和路徑
設定您的版本以包含 echo 領域、伺服器和用戶端:
fx set core.x64 --with //examples/fidl/rust:echo-rust-client-sync
建構 Fuchsia 映像檔:
fx build
執行
echo_realm
元件。這項操作會建立用戶端和伺服器元件 以及轉送功能:ffx component run /core/ffx-laboratory:echo_realm fuchsia-pkg://fuchsia.com/echo-rust-client-sync#meta/echo_realm.cm
啟動
echo_client
執行個體:ffx component start /core/ffx-laboratory:echo_realm/echo_client
在用戶端嘗試連線至 Echo
時,伺服器元件隨即啟動
因此效能相當卓越裝置記錄中會顯示類似以下的輸出內容
(ffx log
):
[echo_server][][I] Listening for incoming connections...
[echo_server][][I] Received EchoString request for string "hello"
[echo_server][][I] Response sent successfully
[echo_client][][I] response: "hello"
[echo_server][][I] Received SendString request for string "hi"
[echo_server][][I] Event sent successfully
[echo_client][][I] Received OnString event for string "hi"
終止領域元件以停止執行並清除元件 執行個體:
ffx component destroy /core/ffx-laboratory:echo_realm