必要條件
本教學課程以入門教學課程為基礎。
總覽
本教學課程的完整程式碼範例位於 //examples/fidl/cpp/server_async_completer。
在初始伺服器教學課程的 Echo
實作項目中,伺服器程式碼會使用完整工具回應 EchoString
要求:
void EchoString(EchoStringRequest& request, EchoStringCompleter::Sync& completer) override {
// Call |Reply| to reply synchronously with the request value.
completer.Reply({{.response = request.value()}});
}
請注意,完整工具的類型結尾是 ::Sync
。必須在處理常式傳回前使用同步完成工具。強制執行這項設定可以最佳化作業,因為製作回覆的簿記中繼資料可以分疊。
非同步回應
在許多情況下,無法同步回應。例如,回覆可能需要來自其他非同步呼叫的結果。如要以非同步方式回應,必須使用 ToAsync
從同步完成工具取得非同步完成工具:
EchoStringCompleter::Async async_completer = completer.ToAsync();
產生的 async_completer
會公開與 completer
相同的 API,但之後可以移除,以供日後使用。
在下方範例程式碼中,伺服器會在延遲工作內傳送回覆,模擬伺服器必須在傳送回應之前執行長時間執行的工作:
void EchoString(EchoStringRequest& request, EchoStringCompleter::Sync& completer) override {
async::PostDelayedTask(
dispatcher_,
[value = request.value(), completer = completer.ToAsync()]() mutable {
completer.Reply({{.response = value}});
},
zx::duration(ZX_SEC(1)));
}
從目前的處理常式方法傳回之前,伺服器不會開始處理任何新的要求。從 EchoString
傳回後,伺服器會監控新 FIDL 訊息的端點,而回覆會排定在未來一秒內傳送。這表示如果用戶端快速連續傳送多個 EchoString
要求,我們可能可以執行太多並行的非同步延遲工作。
在伺服器朗讀傳輸網域物件時以非同步方式回應
當伺服器讀取無線網域物件時,也使用相同的 ToAsync
作業,但請特別留意物件生命週期。特別要注意的是,提供給方法處理常式的要求檢視畫面並不擁有要求訊息的擁有權。如果非同步工作需要在 EchoString
方法傳回後使用要求參數,我們必須將相關欄位複製到擁有的類型:
class EchoImpl : public fidl::WireServer<fuchsia_examples::Echo> {
public:
void EchoString(EchoStringRequestView request, EchoStringCompleter::Sync& completer) override {
// Copy the contents of |request->value| (a fidl::StringView) to a string.
std::string value_owned{request->value.get()};
async::PostDelayedTask(
dispatcher_,
[value = value_owned, completer = completer.ToAsync()]() mutable {
completer.Reply(fidl::StringView::FromExternal(value));
},
zx::duration(ZX_SEC(1)));
}
// ...
};
如要進一步瞭解記憶體擁有權,請參閱傳輸網域物件的記憶體擁有權。
執行範例
為了讓用戶端和伺服器能使用 Echo
通訊協定進行通訊,元件架構必須將 fuchsia.examples.Echo
能力從伺服器轉送至用戶端。
設定建構以納入提供的套件,當中包含 echo 領域、伺服器和用戶端:
fx set core.x64 --with //examples/fidl/cpp/server_async_completer:echo-cpp-async
建構 Fuchsia 映像檔:
fx build
執行
echo_realm
元件。這會建立用戶端和伺服器元件執行個體,並轉送功能:ffx component run /core/ffx-laboratory:echo_realm fuchsia-pkg://fuchsia.com/echo-cpp-async#meta/echo_realm.cm
啟動
echo_client
執行個體:ffx component start /core/ffx-laboratory:echo_realm/echo_client
伺服器元件會在用戶端嘗試連線至 Echo
通訊協定時啟動。裝置記錄 (ffx log
) 中會顯示類似下方的輸出內容。最左邊的資料欄是時間戳記:
[21611.962][echo_server][I] Running C++ echo server with natural types
[21611.965][echo_server][I] Incoming connection for fuchsia.examples.Echo
[21612.998][echo_client][I] (Natural types) got response: hello
[21613.999][echo_client][I] (Natural types) got response: hello
[21614.000][echo_client][I] (Natural types) got event: hello
[21615.002][echo_client][I] (Wire types) got response: hello
[21615.003][echo_client][I] (Natural types) got event: hello
[21615.003][echo_server][I] Client disconnected
請注意,由於伺服器經過程式設計,會以非同步方式將回應延遲一秒,因此 Incoming connection for fuchsia.examples.Echo
和 (Natural types) got response: hello
之間會經過大約一秒。
終止領域元件以停止執行並清除元件執行個體:
ffx component destroy /core/ffx-laboratory:echo_realm