2012-03-02 112 views
0

我目前正在編寫一個允許客戶端登錄的UDP應用程序。之後,他們的端點被存儲在一個列表中。UDP和端口隨機化

private void socket_Callback(IAsyncResult result_) 
{ 
    EndPoint remote = new IPEndPoint(IPAddress.Any, 0); 
    socket.EndReceiveFrom(result_, ref remote); 

    if (!listOfEndPoints.Contains(remote)) 
    { 
     // registration process 

     // add it to list 
     listOfEndPoints.Add(remote) 
    } 
    else 
    { 
     // process packet 
    } 
} 

但是,有時客戶端的NAT會爲每個數據包分配一個不同的外部端點。如果註冊分組的源端點是12.34.56.78:1000,則該端點將被添加到列表中。然而,如果同一個客戶端發送另一個數據包,NAT將爲它分配一個不同的端口,所以它的源端點將是12.34.56.78:1001。 這會導致服務器假定客戶端未註冊並嘗試將該數據包作爲註冊處理。不用說這是行不通的。

解決這個問題的一種方法是發送一個ID(如果它不是超級神祕的話,它很容易僞造)給客戶端。但是,客戶端必須將其添加到發送到服務器的每個數據包中。 因此,這樣做並不是非常有效。

是否有任何其他方式告訴數據包與註冊數據包來自同一個客戶端?

回答

3

您應該肯定使用而不是使用UDP數據包的源IP地址和端口將其與邏輯連接相關聯。如果您收到同一邏輯連接的新IP和端口,則應在每個數據包中包含連接的ID並更新您響應的IP和端口。如果連接hi-jacking存在問題,則可能需要實現某種形式的安全性,例如數據報中的安全校驗和。

TCP處理將數據包與連接關聯起來。使用UDP,您必須自己將數據報與邏輯會話相關聯。我不知道你爲什麼認爲「這樣做不會很有效」。

UDP的一個折衷是,如果你需要TCP提供的任何東西,你必須自己編寫代碼。

順便說一下,我從來沒有見過這樣的港口轉移。你確定客戶端代碼沒有損壞,可能爲它發送的每個數據報打開一個新的套接字。

+0

謝謝!如果這是我的代碼中的一個錯誤,爲什麼我不應該使用數據包的終點?那麼對於每個客戶來說,這不是唯一的嗎?那麼安全校驗和會是什麼樣子?我正在考慮在客戶註冊時向客戶發送一個隨機數字。客戶端然後將md5(分組數據異或校驗和)添加到分組。然後服務器將檢查校驗和的正確性。那是你的意思嗎? – haiyyu 2012-03-02 13:28:21

+1

@haiyyu:不使用端點數據的原因是因爲另一端的IP地址可能會改變。通過TCP,可以理解網絡需要將數據包與會話相關聯,並且NAT設備知道要保留這些IP。使用UDP,他們不會。是的,這就是我的意思。最好的解決方案當然取決於你的要求。 – 2012-03-02 13:42:21