2011-11-29 36 views
2

我已經在Lua中編寫了一個插件,用於通過UDP數據包(512字節)將播放器信息發送到遠程服務器的遊戲,遠程服務器從數據包中讀取數據並將所有播放器信息彙總一個xml文件(然後所有玩家都可以在網頁上查看它們,以便他們可以看到彼此的當前狀態)。DatagramSocket暫時停止接收數據包(Java)

我已經使用DatagramSocket編程服務器在Java中處理傳入的數據包,但我注意到一些奇怪的行爲。經過一段時間後,DatagramSocket似乎暫時停止接受連接約10-12秒,然後再次恢復正常行爲(我不能看到任何異常)。客戶端發送數據包的頻率與發生此行爲的速度之間肯定存在關係。如果我增加客戶端的更新頻率,DatagramSocket將會「儘快」失敗。

值得一提的是,每接收到的數據包都會產生一個處理數據包中數據的線程。我在Linux上運行服務器,如果它有所作爲!

有誰知道什麼可能導致這種行爲發生?

Andrew

+2

我的猜想是你的服務器端沒有接收緩衝區空間。 – NPE

+0

太少細節(例如,您使用的是什麼Linux風格,JVM和Java版本),以及一些代碼會有所幫助;肯定爲每個數據包產生一個新的線程是__bad__想法(使用線程池和/或隊列)。無論如何,考慮UDP是不可靠的。 – Viruzzo

+0

我說錯了一個線程被產生。我正在使用cachedThreadPool和ExecutorService來處理數據包。雖然我知道UDP是不可靠的,但它會突然停止丟棄數據包,特別是當我在本地主機上測試實現時,這是令人懷疑的。我會更深入地瞭解接收緩衝區的大小。 – Andrew

回答

3

UDP是一個網絡協議,絕對沒有交付保證。任何沿途任何網絡組件(包括客戶端和服務器PC本身)都可以決定因任何原因(例如高負載或網絡擁塞)而丟棄數據包。

這意味着你必須花點時間找出發生丟包的位置。你可以使用諸如wireshark之​​類的東西來查看數據包是否到達服務器。

如果可靠傳輸比低延遲更重要,請切換到TCP。如果你堅持使用UDP,你將不得不允許數據包丟失,而不管你是否在這個特定的時間解決這個特定的問題。

+0

雖然可靠的交付不一定是一項重要的要求,但我最終轉而使用TCP,問題似乎已經得到了解決。使用UDP的主要原因是因爲客戶端程序有一個很好的包發送UDP數據包,但我能夠使用LuaSocket創建一個很好的解決方案。 – Andrew

3

我的猜想是你在服務器端的接收緩衝區空間不足。

您可能想重新審視您的設計:產生線程是一項相當昂貴的操作。這樣做對於每個傳入數據包都會導致吞吐量相對較低的系統,這很容易解釋接收隊列建立的原因。

而且,看Specifying UDP receive buffer size at runtime in Linux

附:我相信你已經知道UDP不能保證消息傳遞,所以我不會付諸實踐。

+0

我們可以在android中做同樣的事情嗎?如果長時間操作後填充緩衝區,我們是否可以清除緩衝區?我的問題是聽衆在長時間工作後停止了 –

1

爲每個UDP數據包啓動一個線程是一個壞主意TM。 UDP服務器傳統上被編碼爲簡單的接收循環(畢竟你只需要一個套接字)。這樣你可以避免線程的所有開銷,同步以及沒有的開銷。

+0

+1。如果我在閱讀原始問題方面做得更好,那麼我會回答這個問題: - /。 – Barend