2010-04-09 80 views
10

IM在多個客戶端試圖寫一個服務器/服務是有史以來第二個左右的播放局域網上的消息,有點像一個服務發現。組播報文在同一臺機器

該消息需要由 可能是 同一機器或不同機器 上的多個客戶端程序被接收。但是同時在每臺機器上運行 的程序可能會多於 。

進出口使用Delphi7中,與印9.0.18

其中IM卡是如果我應該使用UDP(TIdUDPClient /服務器)或IP多播(TIdIPMCastClient /服務器)或者它甚至有可能...

香港專業教育學院設法得到它與IP多工作,一臺機器一個客戶投,但即使在具有不同綁定許多改掉..最大/最小端口等等,我似乎無法找到一個解決方案。

回答

8

我認爲你正在尋找SO_REUSEADDR套接字選項。在套接字上設置該選項允許多個套接字在同一個端口上偵聽。對於多播Windows,保證消息將被傳遞到所有套接字(否則該消息只會隨機地進入一個套接字)。

您通常通過調用setsockopt來完成此操作,但我不是Delphi開發人員,所以我不確定您的API是什麼樣的。這個question似乎顯示了一個在Delphi中做類似事情的人的例子。

+0

非常好,SO_REUSEADDR這就是我需要的提示 – 2010-04-14 06:18:33

+1

在mac OSX上,我必須添加: 'sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEPORT,True)' – 2010-05-21 00:25:13

5

我從來沒有做過這個,但它似乎是「郵筒」是你所需要的。它將在本地網絡上廣播一條消息,並從其他知道如何回覆的工作站收到任何回覆。這就是流行的「犰狳」許可證管理器的工作原理(確保註冊密鑰不是「過度訂閱」)。 我的應用程序(ClipMate)使用Armadillo作爲保護包裝(共享軟件包裝)。當註冊用戶運行該應用程序時,它會檢查該相同密鑰是否被同一網絡上的其他機器使用。它基本上說:「我使用許可證1234,你呢?」它等待回覆(我在啓動過程中在一個單獨的線程中這樣做,所以我不會阻止我的啓動)。如果其他工作站報告他們使用的是同一個密鑰,我會根據許可證中包含的席位數來檢查計數。我不能完全肯定這是Windows7的上那樣強勁....

+1

在http://www.funkypuppy.com/上存在一個簡單的郵件插槽實現,它在Delphi 7中運行良好。 – skamradt 2010-04-09 17:33:19

+0

郵件插槽聽起來很有希望。我嘗試從funkypuppy實施,但我似乎無法有超過2個程序在同一臺計算機上接收郵件。也許我做錯了? – 2010-04-11 23:48:15

+0

儘管Windows郵槽是作爲廣播機制「廣告」的,它指的是不同機器上的接收器。在單臺機器上,只有一個進程可以擁有並讀取特定名稱的郵筒。 – 2011-09-26 12:02:53

1

的RemObjects有這個很好的解決方案:ROZeroConf

之前是可用的,我做類似的東西我自己用的RemObjects SDK的TROBroadcastChannel(基於UDP和Indy)。 在該組件內部,它調用TIdUDPBase.Broadcast發送,並且TIdUDPClient.ReceiveBuffer接收響應。

(順便說一句,UDP廣播只能在同一網絡/子網,ROZeroConf是一個更好的解決方案)

2

這是絕對有可能。

重新「UDP或多播」,你說蘋果和桔子。組播是一個IP概念,因此您可以通過多播IP或通過廣播IP愉快地發送UDP

如果你有讓所有客戶端本地鏈路(路由器等,一般不轉發廣播包),我會說只是去與廣播的侷限性確定。 TIdUdpBase.Broadcast將成爲你的朋友。

更新:無論是組播還是廣播,只能有一個套接字綁定到任何特定的IP /端口對。因此,如果你想要多個客戶端都收聽SAME廣播/多播,我想你需要一個額外的調度器客戶端。該調度員客戶端接收廣播並通知機器上的每個客戶端。

在你的每一個客戶端中你都有一個小小的註冊過程,說「嘗試綁定到發送廣播的端口,如果可以的話,在那個端口上設置一個調度器客戶端,如果你不能,調度者已經創建好了,並將自己註冊到該調度員。「

該註冊過程可能與綁定到本地主機IP上任何可用端口一樣簡單,並對調度程序說「請發送廣播到此IP /端口」。

更新:Christopher Chase有正確的想法。我剛剛完成了幾乎相同的解決方案作爲他的,除了我修補IdIPMCastClient,添加一個屬性ReuseAddr:加入

if Self.ReuseAddr then begin 
    SetReuseAddr := Id_SO_True; 
    Bindings[i].SetSockOpt(Id_SOL_SOCKET, Id_SO_REUSEADDR, @SetReuseAddr, Sizeof(SetReuseAddr)); 
end; 

來電來AllocateSocket和綁定之間的布爾和改變TIdIPMCastClient.GetBinding(其中SetReuseAddr:整數)。

+0

感謝您的答案,UDP和多播的侷限性實際上是必需的,即我不希望郵件離開局域網等,但我似乎無法解決的問題是有兩個客戶端在同一臺計算機上偵聽廣播 – 2010-04-13 00:08:31

+0

我在Indy 10中添加了一個新的ReuseSocket屬性到TIdIPMCastClient。 – 2010-05-21 01:01:19

1

與shf301提示,這是我得到它與

工作的代碼我創建了一個新的TIdIPMCastClient

TIdReUseIPMCastClient = class(TIdIPMCastClient) 
    private 
    procedure SetReUseAddr(InBinding: TIdSocketHandle; const Value: boolean); 
    protected 
    function GetBinding: TIdSocketHandle; override; 
    public 
    end; 

添加的程序

procedure TIdReUseIPMCastClient.SetReUseAddr(InBinding: TIdSocketHandle; const Value: boolean); 
var 
    tempi: integer; 
begin 
    if Assigned(InBinding) and InBinding.HandleAllocated then 
    begin 
    tempi := iif(Value, 1, 0); 
    InBinding.SetSockOpt(Id_SOL_SOCKET, Id_SO_REUSEADDR, PChar(@tempi), SizeOf(tempi)); 
    end; 
end; 

複製GetBinding來自TIdIPMCastClient的代碼,並在綁定之前添加SetReUseAddr

Bindings[i].AllocateSocket(Id_SOCK_DGRAM); 
    SetReUseAddr(Bindings[i], True); 
    Bindings[i].Bind; 
+0

我在Indy 10中添加了一個新的ReuseSocket屬性給TIdIPMCastClient。 – 2010-05-21 01:03:55

相關問題