2012-02-17 45 views
2

我需要通知一對多客戶端執行任務(重新加載)。服務器可能會或可能不會在任何給定的時間點運行。 (出於這個原因,我有一些困難,定義誰是客戶,誰是服務器)。一種適用於我的情況的IPC形式

在任何給定時間內,服務器可能會開始運行。當服務器關閉時,它會通知所有客戶執行他們的任務。

我試圖用一個NamedPipeServerStream並在「客戶端」(記住的關係如此奇和我一起承擔)運行多個實例。不幸的是,我只能爲任何給定的服務器名稱創建一個管道服務器。所以這不起作用。我可以讓客戶不斷檢查服務器,但是如果我要開始輪詢,那麼我也可以直接輪詢數據庫。

我的情況大致類似於觀察者模式。我不需要動態訂閱/取消訂閱。我確實希望服務器向所有正在運行的客戶端推送通知以執行任務。

我該如何做到這一點?請記住,我必須在IPC上做到這一點。服務器/客戶端在不同的進程下運行,並始終在同一臺計算機上運行。

+0

服務器進程和許多客戶端進程**保證**是在同一臺機器上,還是服務器駐留在網絡地址上? – 2012-02-17 15:15:15

+0

@ScottChamberlain - 同一臺機器。如果UDP或某種形式的網絡通信是唯一的方式來做到這一點,那麼我願意接受。 – 2012-02-17 15:16:35

+0

保證是同一臺機器打開更多的選擇。 – 2012-02-17 15:19:34

回答

3

要解決輪詢問題,您可以創建客戶端進程將偵聽的名爲ManualResetEvent。客戶端將啓動一個線程,然後等待事件,當服務器啓動時它將發出事件信號,讓所有客戶端啓動他們的偵聽代碼,這些代碼可以像當前一樣打開命名管道。查看EventWaitHandle.GetAccessControl MSDN頁面,查看如何創建一個名爲ManualResetEvent的示例。

對於你的I can only create one Pipe server for any given server name.問題,如果有多個服務器運行如何客戶端應該知道哪個服務器連接到?你說這是一個服務器*客戶關係。如果你要運行多個服務器,你需要一種方法來告訴客戶端它應該聽哪個服務器。

+0

我沒有意識到你可以觸發跨進程邊界的事件。你確定這有效嗎?關於第二部分,只有一臺服務器。客戶端只響應這1個服務器。 – 2012-02-17 15:43:52

+0

是的,我鏈接的頁面上的示例完全是這樣的,它通過同一程序的兩次執行發出ManualResetEvent(第一次啓動爲「服務器」('doesNotExist = true'),第二次檢測已命名的ManualResetEvent存在('doesNotExist = false')自動進入「客戶端」)。 – 2012-02-17 15:46:26

+0

@Scott我不知道.Net的EventWaitHandle很容易讓你附加到已命名的事件 - 我一直在使用p/invoke像一個白癡。如果我能兩次投票,我會。 – 2012-02-17 15:53:48

0

使用命名的共享內存將是實現一對多通信的一種方式。服務器可以創建共享內存,並且一個或多個客戶端可以打開並讀取它。 An example (in C) is shown here。另外,a .NET example is shown here

共享存儲器將存在如只要至少一個進程已打開的句柄給它。從OP開始,這聽起來好像是一個有用的功能,因爲即使服務器進程關閉(只要至少有一個客戶端仍然打開它),內存仍然可以繼續存在。 .NET示例還顯示瞭如何持久保存這些信息,如果這些信息必須經過這些過程纔會有用。

根據所需的時間,客戶可以定期地讀取所需信息的存儲。或者,如果存在更加時間緊迫的情況,則可以使用已命名的信號向客戶端發出信號,以執行必要的操作。以信號量作爲同步對象,您可以通過將釋放計數設置爲大於1的值來發信號通知多個客戶端。

1

因爲你指定的進程都保證是在同一臺機器上,我可能會看使用Windows named event。您的客戶和服務器可以撥打OpenEvent,如果事件尚未創建,請致電CreateEvent。這將爲您提供一些控制(使用pulseevent,設置/重置等),瞭解每個事件發佈的客戶端數量,還允許您在服務器不存在的情況下打開客戶端。

正如Scott建議,可以輕鬆地做到這一點在C#中使用。網名爲EventWaitHandle,通過調用一個帶字符串的構造函數(如this one)。這將爲您創建系統範圍的同步對象。這個特定的構造函數也會告訴你,如果你是第一個請求這個事件(你創建它),或者它已經存在。

相關問題