2013-06-26 50 views
3

我有一個基於UDP Netty的服務器。它有一個SimpleChannelUpstreamHandler流水線,我重寫了messageReceived方法。Netty - UDP服務器

我現在需要回寫一些信息。我只能通過使用來自MessageEvent.getRemoteAddress()的套接字信息和來自MessageEvent.getChannel()的通道來做到這一點。爲了能夠重複使用這些信息,我保存在一張靜態地圖中。

這變成MessageEvent.getChannel().write("foo", MessageEvent.getRemoteAddress());

我本來期望是有MessageEvent.getChannel().getRemoteAddress()工作,這是情況並非如此。它總是給我null

  1. 我做錯了什麼?
  2. 寫回來比保留某些成員的頻道和遠程地址更好嗎?

回答

4

當使用UDP(數據報)通道作爲服務器通道時,只能將其綁定在本地地址上,並且不建立連接。這就是爲什麼沒有與該頻道相關聯的遠程地址,並且您在致電MessageEvent.getChannel().getRemoteAddress()時總是得到null。這種行爲是預期的並且是正確的同一個UDP「服務器」通道處理所有傳入的客戶端請求。

當使用UDP通道作爲客戶端通道時,可以通過將通道連接到遠程地址來創建「連接」。在這種情況下,通道將有一個配置的遠程地址(儘管沒有實際的連接),並且調用MessageEvent.getChannel().getRemoteAddress()將返回配置的遠程地址。 連接UDP通道可防止用戶使用通道將數據發送到通道中配置的遠程地址以外的遠程地址。試圖這樣做會引發異常。在UDP中連接客戶端通道是可選的,只要保存遠程地址,客戶端就可以使用只綁定在本地地址上的通道正常工作。

我認爲你有兩個選擇:

  1. 節省了客戶端的遠程地址與客戶端標識與使用「服務器」通道發送的數據。保存頻道將不起作用,因爲同一頻道將用於與所有客戶端進行通信。
  2. 爲每個客戶端創建一個新的連接通道,並使用客戶端標識符保存新通道。

我相信第一種方法更好。

2

正如你可能知道UDP是無連接傳輸。單個通道可以從任何目標地址接收數據並將數據寫入任何目標地址。因此,UDP通道沒有像TCP通道那樣具有關聯的遠程地址。雖然我認爲可以通過netty將UDP通道與特定的遠程地址關聯起來,但我還沒有掌握細節,說實話,我認爲從消息事件中獲取地址是更好的選擇。

這導致你的第二個問題,那就是,你需要將遠程地址保存在某個地方。我在Netty中沒有做過任何UDP編程,因此我不確定是否需要將遠程地址映射到通道對象,或者Netty是否總是返回相同的通道對象。這是值得檢查的,因爲您可能只需要保持對頻道的單一引用。

+0

謝謝!我本來期望的是通過頻道獲得遠程地址供以後使用。如果這不切實際,也許拋出一個不受支持的操作異常會更好。 關於頻道引用,我不知道我是否做得對。我期待多個客戶端連接,每個客戶端都會發送一些數據以及唯一的客戶端標識符。我把頻道映射到這個唯一的標識符。想法? – thelost

2

1)看看這個UDP upstream handler。要獲得發件人的遠程地址,您可以使用以下代碼SocketAddress remoteAddress = datagramPacket.sender();
2)@johnstlr提到的是正確的,將UDP通道與單個遠程地址關聯是不正確的。但是,您可以使用併發哈希映射來執行查找,如上面的文件中所示。這個game server實際上使用具有TCP和UDP連接的會話。這使得通過TCP發送可靠數據以及通過UDP發送所有幀數據變得容易。