管理多个UDP套接字的超时

时间:2011-09-23 19:04:35

标签: c++ sockets timeout udp

我必须在Windows和Linux上为大学课程编写TFTP(普通文件传输协议)服务器。我正在使用C ++,我想使用一个线程和select()来检查新的传入数据包。 TFTP要求如果数据包未被确认一段时间,则重新发送数据包。我想知道管理这些多次超时的最佳方法是什么。

我正在考虑创建一个std :: list,它包含将连接与超时发生的绝对时间相关联的对象。通过增加超时时间来排序列表(所有超时在分配时都是相同的,因此新的超时总是最大的并且可以到列表的末尾 - 否则我需要一个地图而不是列表。)登记/> 由于我需要重置连接的超时,如果数据包及时到达,我想创建一个std :: map,它将一个连接与一个指向它在列表中的位置的迭代器相关联。更新连接超时时,可以快速找到列表中的元素,更新并移动到列表末尾(再次假设新的超时最大)。

这是处理问题的好方法还是有更简单的方法?

1 个答案:

答案 0 :(得分: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
    }
}

要删除连接,您必须从一个集合中删除指针,然后从另一个集合中删除AND删除指针。

我没有编译它所以不要指责我错别字(: