2011-09-23 35 views
0

我必須在Windows和Linux上爲大學課程編寫一個TFTP(平凡文件傳輸協議)服務器。我使用C++,我想使用一個線程,並選擇()來檢查新的傳入數據包。 TFTP要求如果數據包在一定的時間內未被確認,那麼數據包將被重新發送。我想知道管理這些多個超時的最好方法是什麼。管理多個UDP套接字的超時時間

我正在考慮創建一個std :: list,它包含將連接與發生超時的絕對時間相關聯的對象。該列表是通過增加超時時間來排序的(所有超時在分配時都是相同的,所以新的超時總是最大的並且可以到達列表的末尾 - 否則我需要一張地圖而不是列表)。
因爲我需要重置連接的超時時間,如果數據包及時到達,我想創建一個std :: map將一個連接與指向它在列表中的位置的迭代器關聯起來。當連接超時更新時,列表中的元素可以快速找到,更新並移動到列表的末尾(再次假定新的超時是最大的)。

這是處理問題的好方法,還是有什麼簡單的方法?

+1

沒錯這就是罰款;) –

+1

很相似:http://stackoverflow.com/questions/7075472/scalable-algorithm-to- detect -stale-data/7084735#7084735 –

+0

小心保持迭代器指向你要修改的列表。在這種情況下,將項目移動到列表的末尾將會使地圖持有的迭代器無效。 – Gabriel

回答

1

如果我理解正確,您有連接/超時對,並且您希望能夠通過連接和超時訪問這些對。 通過連接,因爲您必須在接收數據包時更改超時,並且由於需要知道下一個超時連接是什麼而超時。

如果您對提升沒有任何反應,請參閱multi_index

如果你想推出自己的,你可以保留兩組指針,給人以設置不同的比較功能:

class Connection { 
    ... 
public: 
    int GetTimeout() const; 
    int GetID() const; 
}; 

class TimeIsLess { 
public: 
    bool operator()(const Connection*c1, const Connection*c2) const { 
     return c1->GetTimeout() < c2->GetTimeout(); 
    } 
} 
class IdIsLess { 
public: 
    bool operator()(const Connection*c1, const Connection*c2) const { 
     return c1->GetId() < c2->GetId(); 
    } 
} 

std::set<Connection*,TimeIsLess> connectionsByTime; 
std::set<Connection*,IdIsLess> connectionsById; 

要創建連接:

... 
Connection * c = new Connection(id, timeout); 
connectionsByTime.insert(c); 
connectionsById.insert(c); 
... 

要獲得下一個連接將超時,只是得到第一個:

auto nextToTimeout = connectionsByTime.begin(); 
if (nextToTimeout != connectionsByTime.end()) 
{ 
    if ((*nextToTimeout)->GetTimeout() < now) 
    { 
     // Close the connection 
    } 
} 

要刪除連接,你的h ave從一組中刪除指針,並從另一組中刪除並刪除指針。

我編譯沒有它,所以不要釘箱上的錯別字(:

+0

謝謝。這就是我要做的。實際上必須做一個修改版本,它使用一個地圖和一個集合。我想寫一個可用於其他超時的通用類​​。所以我將會有一個名爲TimeoutKeeper的類,它將一個對象與其超時關聯起來。所以我的兩個系列將會是一張地圖 *>,就像你建議的一套 *>。再次感謝您的幫助。 – tommazzo

+1

@tommazzo很高興爲您提供幫助(:嘿,也許你想把管家封裝在一個類中,它可以包含(並且隱藏)地圖和集合,它可以有一個AddConnection(),一個GetConnectionByTime(),一個GetConnectionByID()和RemoveConnection()我也喜歡區別Get ...(),它爲給定對象搜索內部結構,如果找不到則添加它,Find ...()只搜索對於給定的對象,返回NULL或錯誤代碼,當找不到時乾杯! – Gabriel

+0

當然,我將所有這些封裝在一個單獨的類中,實際上我想在同一個程序中的另一個場景中重新使用它,我必須管理緩存中文件映射的超時(方法將具有通用名稱,例如addElement())。 再次感謝您的幫助。 – tommazzo