2011-09-23 77 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