2017-08-11 34 views
0

我一直在尋找製作一個簡單的基於套接字的Java遊戲,並在多個地方閱讀客戶端套接字在單次交換後被銷燬。這是持續聯繫的良好做法嗎?服務器需要保持與客戶端的連接(即,每次想要告訴客戶端某事時都不使用socket.accept()),但不能每次都等待客戶端的響應。我已經將服務器/客戶端運行在不同的線程中,但是在每次交換意味着重新獲取(或無法重新獲取)到該客戶端的連接後,不會銷燬套接字?我見過很多關於Java套接字的衝突網站,以及它們應該如何實現。單次使用後銷燬套接字是個好主意嗎?

+1

你的問題太廣泛了。你應該描述一個具體的問題,你有。如果客戶端需要連接到服務器的連接,它通常不會關閉該連接。關閉並重新打開連接可能會花費相當長的時間,並且會降低速度。在其他情況下,關閉連接或使用不需要像UDP這樣的連接的不同協議可能是有意義的。 – Guenther

+0

這取決於。編程實踐/ Java很少有模型可以使用套接字,從池到服務器庫(即程序員不需要使用原始套接字)以及更少。有些具有非常好的優化。你的使用場景是什麼? –

+0

Socket-per-request爲您節省了一大類錯誤(超時,keepalive,客戶端 - 服務器不同步),但是以吞吐量爲代價。建立連接的時間可能很長,並且每次創建新套接字時,TCP性能優化算法都必須重新開始。 –

回答

-1

沒有硬性規定,但它取決於你想達到的數據速率。

例如,YouTube是一個流式視頻服務,但視頻數據是通過客戶端使用https傳遞以獲取批量視頻數據。沒有效率,是的,但很容易編程。有很多原因可以將https用於YouTube等應用程序(防火牆等),但最終的省電和網絡性能不是其中之一。 「正確的」方法是使用像RTP這樣的協議,它使用UDP來傳遞小數據包,然後可以按順序重新排列,還必須處理編解碼器級丟失的幀等等。很少的網絡流量,對帶寬受限的網絡鏈接很友好,但是在處理穿越防火牆,客戶端軟件等時更加困難。

因此,如果您的遊戲發送的數據量適中,唯一的問題是設置和拆除每個消息的整個套接字連接是你自己會有的嘮叨感覺,它在某種程度上不是最有效的解決方案。

儘管聽起來好像在客戶端/服務器之間需要進行通信以及需要在等待通信完成時處理其他內容的需求之間存在衝突。在這裏你將進入異步I/O領域。爲了使這一點很容易,我強烈建議你看看ZeroMQ--這會讓所有事情變得簡單得多。

+0

唯一錯誤的是它*不是最有效的解決方案。沒有'嘮叨的感覺'或'不知何故'。它浪費了每個消息七個數據包交換。 – EJP

+0

@EJP,自從交換數據包的數量是什麼時候被選作唯一的,不可侵犯的「效率」措施?從那時起,一些額外的流量「錯誤」了?效率和正確性對不同的人意味着不同的事情,而且大多數人早已不再擔心試圖將網絡流量降低到最低水平;生命太短暫了。 – bazza

+0

@bazze沒有人對「唯一的,不可侵犯的」做任何說明,但是從何時起,額外的流量不會比沒有額外的流量效率更低?自從什麼時候有人的感覺與它有什麼關係?鑑於HTTP Keepalive所付出的巨大努力,您的最終評論顯然是不真實的。 – EJP

-1

並在多個地方讀取客戶端套接字在單次交換後被銷燬。

只在實際發生的地方。它有許多上下文,其中最突出的例子是HTTP,其中盡最大努力重用連接。

這是持續連接的良好實踐嗎?

這個問題是矛盾的。持續連接是未關閉的連接。關閉的連接不能繼續。

服務器需要維護與客戶端的連接(即,每次想要告訴客戶端某事時都不使用socket.accept()),但不能每次都等待客戶端的響應。

你在這裏摸索的詞是'會話'。

我已經在單獨的線程中運行服務器/客戶端,但每次交換意味着重新獲取(或無法重新獲取)到該客戶端的連接後不會銷燬套接字?

是的。

我見過這麼多衝突的網站有關Java中的套接字以及它們應該如何實現。

您應該在客戶端使用連接池;在服務器上尋找每個連接多個請求的請求循環;一個客戶端設備,在某些空閒超時後關閉空閒連接;並在服務器上讀取超時,關閉在超時時間內沒有讀取請求的連接。

相關問題