サービス/デーモンが開始され、着信接続を処理できることを複数のクライアント アプリケーションに通知するクロス プラットフォームの方法を探しています。クライアントは常に実行されていますが、サービスは実行されていない場合があります。通常、サービス/デーモンはコンピューターの起動時に自動的に開始されますが、場合によっては開始されない場合があり、そのような場合、サービス/デーモンの開始時にクライアントが自動的に接続する必要があります。
クライアントの基本的な流れは、サービスが実行されていることに気付くまで待ってから接続することです。接続が中断された場合、または接続できなかった場合は、最初からやり直します。
Windows の場合、クライアントがこのイベントを待機できるように、開始時にサービスがグローバル イベント オブジェクトを通知するソリューションがあります。これは実際には問題なく動作しますが、すべての潜在的なケース (サービスのクラッシュや実行中のサービスの複数のインスタンスなど) を処理できるわけではないことは確かです。サービスが実行されていなくても、クライアントが時々「誤って」起動してもかまいません。クライアントが常に接続しようとするビジー ループに入るのを避けたいだけでなく、同時にサービスの開始に非常に迅速に応答することも避けたいのです。つまり、接続試行の間にスリープを追加するだけではあまり効果がありません。
サービスが実行中であり、接続を受け入れる準備ができているかどうかを検出するクロスプラットフォームの方法はありますか?
更新:現在のメカニズムが Windows でどのように機能するかについて、メモリからの近似コードを使用してもう少し情報を追加します。
サービス:
SECURITY_ATTRIBUTES sa;
// Set up empty SECURITY_ATTRIBUTES so that everyone has access
// ...
// Create a manual reset event, initially set to nonsignaled
HANDLE event = ::CreateEvent(&sa, TRUE, FALSE, "Global\\unique_name");
// Signal the event - service is running and ready
::SetEvent(event);
// Handle connections, do work
// If the service dies for whatever reason, Windows deletes the event handle
// The event is deleted when the last open handle to it is closed
// So the event is signaled for at least as long as the service lives
クライアント:
while (true) {
// Set up event the same way as the service, including empty security attributes
// ...
HANDLE event = ::CreateEvent(&sa, TRUE, FALSE, "Global\\unique_name");
// Wait for the service to start
DWORD ret = ::WaitForSingleObject(event, INFINITE);
// Close the handle to avoid keeping the event object alive
// This isn´t enough in theory, but works in real usage as the number of clients
// will always be low
::CloseHandle(event);
// Check if we woke up because the event is signaled
if (WAIT_OBJECT_0 == ret) {
// connect to service, do work
// ...
}
}
OS X と Linux でほぼ同じことを達成するにはどうすればよいですか?