Управление таймаутами для нескольких сокетов UDP - PullRequest
0 голосов
/ 23 сентября 2011

Мне нужно написать TFTP (Trivial File Transfer Protocol) сервер для Windows и Linux для университетского курса.Я использую C ++, и я хочу использовать один поток и выберите (), чтобы проверить наличие новых входящих пакетов.TFTP требует, чтобы, если пакет не был подтвержден в течение определенного периода времени, пакет был повторно отправлен.Мне интересно, как лучше всего управлять этими несколькими тайм-аутами.

Я думал о создании std :: list, который содержит объекты, которые связывают соединение с абсолютным временем, в которое происходит тайм-аут.Список упорядочен по возрастанию времени ожидания (все таймауты одинаковы при назначении, поэтому новый таймаут всегда самый большой и может идти до конца списка - в противном случае мне нужна карта вместо списка).
Так как мне нужно сбросить время ожидания для соединения, если пакет приходит вовремя, я хочу создать std :: map, который связывает соединение с итератором, указывающим на его место в списке.Когда тайм-аут соединения обновляется, элемент в списке можно быстро найти, обновить и переместить в конец списка (опять же, при условии, что новый тайм-аут самый большой).

Это хороший способ обработкипроблема или есть что-нибудь попроще?

1 Ответ

1 голос
/ 24 сентября 2011

Если я правильно понимаю, у вас есть пары соединение / время ожидания, и вы хотите иметь возможность доступа к этим парам по соединению, а также по времени ожидания.По соединению, потому что вы должны изменить время ожидания при получении пакета, и по истечении времени ожидания, потому что вам нужно знать, какое будет следующее соединение с временем ожидания.

Если вы не имеете ничего против повышения, взгляните на 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
    }
}

Чтобы удалить соединение, вам нужно удалить указатель из одного набора,и удалите И удалите указатель из другого набора.

Я не скомпилировал ничего из этого, так что не приставайте к опечаткам (:

...