2014-01-14 72 views
0

我建立一個UDP客戶端,可以選擇不同的服務器進行通信。鑑於NIO應用程序涉及使用單個接收線程,我如何將傳入數據報派送到我的應用程序的正確部分?即將輸入分組與輸出分組相關聯。從理論上講,發送(或連接?)到服務器時,應該可以在傳出數據報中獲取源IP /端口,然後通過檢查目標IP /端口來識別傳入數據包作爲其響應。 (因爲:http://www.dcs.bbk.ac.uk/~ptw/teaching/IWT/transport-layer/source-destination.gif的Java NIO UDP客戶端與多個服務器

大多數UDP客戶端的實例似乎是假設在單一服務器上,以便識別傳入的數據報以傳出數據報的響應是微不足道的,例如:

ByteBuffer textToEcho = ByteBuffer.wrap("blah"); 
ByteBuffer echoedText = ByteBuffer.allocateDirect(MAX_PACKET_SIZE); 

DatagramChannel datagramChannel = DatagramChannel.open(StandardProtocolFamily.INET) 
datagramChannel.connect(new InetSocketAddress(REMOTE_IP, REMOTE_PORT)); 

while(true) 
{ 
    int sent = datagramChannel.write(textToEcho); 
    datagramChannel.read(echoedText); 
} 

也許我可以使用多個DatagramChannels和迭代調用每個read(),將數據調度到適當位置,以便我的應用程序預期響應?

回答

-2

你應該打開一個單獨的數據報通道與您希望通信的每個服務器上,並用手關閉該通道的管理(讀/寫)到一個單獨的線程。

+0

因此,在這種情況下,我將每個服務器有一個線程在客戶端上?我應該補充說,客戶端實際上是一個代表客戶端將消息中繼到另一個本地服務器的服務器。考慮到會有很多(實際的,非本地的)客戶,如果可能的話,我想避免每個客戶的線程。 – user1478842

+0

或者你的意思是說我可以有專門的讀寫線程發送到多個通道。 我對NIO風格編程的印象是,我們通常使用單個DatagramChannel,但多路複用。我知道如何發送(只需指定目標IP:端口)時復,但我不知道如何與一個DatagramChannel在客戶端上接收復用的時候,這就是我試圖找出答案。 – user1478842

+0

如果你真的只想要一個頻道,那麼是的:一條線是要走的路。一個通道意味着一個端口,因此您必須檢查傳入的數據包源地址以區分服務器。我會添加另一個答案來解釋如何。 –

0

如果您僅使用一個通道(以及一個綁定的本地端口)進行設置,則需要避免使用connectwrite方法。相反,使用send方法。

  1. 通過您的服務器循環,使用每個服務器的send方法。您可能需要每個sendrewind()你的字節的緩衝區...我不知道,如果send克隆緩衝區與否。
  2. 當所有服務器已發送:在一個循環中,只要有是沒有響應的服務器,使用receive兩全返回的數據(緩衝參數),並返回它(該方法的返回值的服務器)。保持循環,直到服務器列表耗盡,但您希望對循環本身設置時間限制(對於死亡服務器或丟失的數據包)

理想情況下,在接收循環中,您希望receive方法阻止在超時之前的一小段時間。如果您找不到配置阻止的方法,則可以使用非阻塞方式,然後將Thread.sleep放入循環中。試着讓時間阻止工作,但這是最好的方法。

+0

我想我跟着你,但這裏是我的知識中有差距的地方...... 我知道我可以通過檢查receive()返回的ip地址來識別哪個服務器正在返回數據,因爲ip地址對服務器是唯一的。但是,我的客戶端可能會有多個「流」也會轉到同一臺服務器。在這種情況下,我的應用程序(客戶端)當然需要知道傳出端口的源IP和端口,以便它能夠適當地複用響應。 假設這是正確的方法,我將如何獲得源IP? – user1478842

+0

爲什麼你需要源IP?您的客戶端通道綁定到IP和端口,任何發送到該IP和端口的通道都將被您的通道接收。您在該頻道上發送和接收的所有內容都使用相同的IP和端口,因此即使您可以讀取傳入的目標信息包,它也始終保持不變。 UDP中沒有任何東西可以幫助區分使用同一服務器的多個對話。您需要自己將這些信息包含在有效載荷中:制定您自己的協議。這聽起來像TCP會是你正在做的更合適的協議。 –

+0

「UDP中沒有任何東西可以幫助區分使用同一臺服務器的多個對話。」但我認爲按照慣例,傳出數據包有一個源端口,並且他們的響應以目標端口的形式返回(如下圖所示:http://www.dcs.bbk.ac.uk/~ptw/教學/ IWT /傳輸層/源destination.gif)。 這是DatagramChannel.connect()用於接收適當的適當響應數據包的原因嗎? 也許這在理論上是可能的,但是java並沒有提供這樣做的手段。 – user1478842