2011-11-14 56 views
1

我正在使用Java DatagramSocket將數據傳輸到多個不同的客戶端。當我自己處理當前註冊的客戶端列表時,我只將套接字綁定到服務器端口,並且不連接到任何特定的客戶端。使用Java套接字處理不可達UDP端口

但是,通過不使用connect(),我失去了DatagramSocket對無法訪問端口的ICMP通知的響應能力,如果其中一個客戶端死亡並且沒有機會正確註銷服務器。

有沒有什麼辦法讓這種行爲回來?我想爲每個客戶端使用一個DatagramSocket,但這似乎並不可行,因爲它們都必須綁定到服務器上的相同端口(據我所知,在UDP中是不可能的)。

我知道,我不能保證我的服務器能夠看到ICMP消息,我會實現某種超時機制來處理這種情況,但是對ICMP消息的反應將允許我立即停止傳輸給任何沒有運行客戶端的主機,這對流媒體客戶端用戶來說似乎是件好事。

回答

1

如果你想要可靠的點對點連接,我會使用TCP。

但是,如果你想要UDP,我會建議你的客戶端發送心跳信號,這樣發佈者可以超時停止發送的用戶。我假設你不需要連接是可靠的,但它仍然值得用戶將數據包發送回發佈者。

+1

我不希望可靠的溝通,但我也不希望洪水無辜的用戶(對他們)毫無意義的交通;) 我可能會去心跳選項。 – lxgr

+1

如果您有智能路由器,他們只會將UDP流量轉發到正在監聽該流量的服務器。它確實浪費了服務器上的資源。 –

+0

這不是我擔心的服務器(它只能得到非常小的,偶爾會被新用戶請求) - 這是用戶可能會得到不必要的數據。我的應用程序是音頻流媒體,客戶端可能會崩潰或強制關閉,而無需從服務器正確註銷。我沒有看到我和用戶之間的路由器如何區分這種情況與用戶只是繼續監聽的情況(除了路由器是將用戶主機的ICMP消息考慮在內的狀態防火牆除外)。 – lxgr

0

它只是被連接的UDP套接字拋出的原因在於它是如何在'C'級別工作的,的原因是,它是異步的,沒有其他方式可以告訴哪個目標地址造成了這種情況,因爲你在'C'級擁有的只是一個errno,而不是ICMP消息本身的內容。所以要「讓行爲回來」,你確實需要爲每個客戶端連接一個套接字。如果這樣做不實際,你只能依靠應用程序確認的存在與否。