在 Rust 中實作同步 FIDL 用戶端

必要條件

本教學課程假設您已熟悉如何編寫及執行 Fuchsia 並實作 FIDL 伺服器,兩者都包含在 FIDL 伺服器教學課程。如需完整的 FIDL 教學課程,請參閱 總覽

總覽

本教學課程將實作 FIDL 通訊協定的用戶端並執行 針對上一個教學課程中建立的伺服器執行測試。這個架構中的用戶端 教學課程是同步性的我們也提供替代的教學課程 非同步用戶端。

若您想要自行編寫程式碼,請刪除下列目錄:

rm -r examples/fidl/rust/client_sync/*

建立元件

examples/fidl/rust/client_sync 建立新的元件專案:

  1. main() 函式新增至 examples/fidl/rust/client_sync/src/main.rs

    fn main() {
      println!("Hello, world!");
    }
    
  2. 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" ]
    }
    
  3. 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" },
        ],
    }
    
    
  4. 建立元件後,請確定能將其新增至 建構設定:

    fx set core.x64 --with //examples/fidl/rust/client_sync:echo-client
  5. 建構 Fuchsia 映像檔:

    fx build

編輯 GN 依附元件

  1. 將下列依附元件新增至 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",
      ]
    
    
  2. 然後在 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_serviceadd_fidl_service 等條件。如果相符的 service_name 存在,則會使用提供的管道呼叫 service_startup_func,以連線至新服務。
  • 系統會使用 RequestStream 呼叫 IncomingService::Echoadd_fidl_service 註冊的 Echo FIDL 通訊協定 (類型管道)。 傳入的要求管道會儲存在 IncomingService::Echo 中,並新增至 for_each_concurrent 會將 ServiceFs 消耗成類型的 Stream IncomingService。系統會針對串流中的每個項目執行處理常式,以比對傳入 要求及分派給 run_echo_server。每個呼叫所產生的 Future ServiceFs 串流為 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 伺服器傳送至用戶端在本教學課程中 運作範圍 元件是 來宣告適當的功能和路徑

  1. 設定您的版本以包含 echo 領域、伺服器和用戶端:

    fx set core.x64 --with //examples/fidl/rust:echo-rust-client-sync
  2. 建構 Fuchsia 映像檔:

    fx build
  3. 執行 echo_realm 元件。這項操作會建立用戶端和伺服器元件 以及轉送功能:

    ffx component run /core/ffx-laboratory:echo_realm fuchsia-pkg://fuchsia.com/echo-rust-client-sync#meta/echo_realm.cm
  4. 啟動 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