2010-12-29 34 views
20

Odczytywanie innych wpisów przepełnienia stosu i dokumentacji boost::asio potwierdziło, że nie ma synchronicznych wywołań odczytu/zapisu ASIO, które również zapewniają łatwy w użyciu limit czasu jako parametr połączenia.C++ Boost ASIO: jak czytać/pisać z limitem czasu?

Jestem w trakcie konwersji old-schoolowego gniazda Linux-a z wybranymi (2) połączeniami, które wykorzystują limity czasu i muszę zrobić mniej więcej to samo.

Jaki jest najlepszy sposób na zrobienie tego w boost::asio? Patrząc na dokumentację Asio, jest wiele mylących przykładów różnych rzeczy związanych z timerem, ale jestem bardzo zdezorientowany.

Chciałbym zobaczyć prosty do odczytania przykład: Odczytać z gniazda, ale odczekać maksymalnie X sekund, po którym funkcja albo wraca z niczym, albo wraca z czymkolwiek, co było w stanie. do odczytu z gniazda przed upływem limitu czasu.

+3

Proszę wyjaśnić, co jest mylące w tym przykładzie: http://think-async.com/Asio/asio-1.4.7/src/examples/timeouts/blocking_tcp_client.cpp - Zasadniczą logiką jest, że despatch 2 asynchroniczne zadania, jeden odczyt/zapis, a drugi to time-out, jeśli odczyt/zapis zwróci najpierw zabicie terminatora, jeśli timer zwróci logikę to odczyt/zapis jest wciąż wyjątkowy - od tego momentu kontynuujesz swoją logikę time-out. bardzo, bardzo prosty. –

+2

Istnieje jedna narożna sprawa, która może pojawić się w sieci hf, która jest związana z kolejkowaniem wywołań zwrotnych. licznik czasu oczekiwania cb jest w kolejce, a następnie odczyt/zapis jest w kolejce. napotkasz timeout cb i zaczniesz wykonywać logikę time-out, kiedy w rzeczywistości skończy się odczyt/zapis, możliwe rozwiązanie, które widziałem, jest podobne do blokady podwójnego sprawdzania - w skrócie wykonaj dodatkowy czas oczekiwania po zwrocie pierwszego czasu, ale to ma taki sam problem, jeśli odczyt/zapis jest w kolejce po drugim limicie czasu jest kolejka ... –

+2

Po prostu pamiętaj, że limit czasu jest trudnym warunkiem, mówisz, że nie dostanę czegoś w pewnej ilości czas, zrobię coś konkretnego - dotyczy to również faktu, że odczyt/zapis mógł już się odbyć i jest na dobrej drodze, co nie zmienia faktu, że nie otrzymałeś go jeszcze. –

Odpowiedz

6

Zostało to poruszone na listach mailingowych Asio, jest też ticket z żądaniem funkcji. Podsumowując, zaleca się stosowanie metod asynchronicznych, jeśli zależy Ci na limitach czasu i możliwości anulowania.


Jeśli nie można konwertować do metod asynchronicznych, można spróbować opcji gniazda SO_RCVTIMEO i SO_SNDTIMEO. Można je ustawić za pomocą setsockopt, deskryptor można uzyskać za pomocą metody boost::asio::ip::tcp::socket::native. Strona man 7 socket człowiek mówi

SO_RCVTIMEO i SO_SNDTIMEO Określ odbiera lub wysyła limity czasu aż zgłoszenie błędu . Argumentem jest czas struktury struct. Jeśli blok funkcyjny na wejściu lub wyjściu dla tego okresu czasu i dane zostały wysłane lub odebrane, wartość zwracana tej funkcji będzie wynosiła ilość przesłanych danych; Jeśli dane nie zostały przesłane i upłynął limit czasu wynoszący , wartość -1 wynosi wrócona z ustawieniem errno na EAGAIN lub EWOULDBLOCK, tak jak gdyby gniazdo zostało określone na , bez blokowania. Jeśli limit czasu to ustawiony na zero (domyślnie), to operacja nigdy nie przekroczy limitu czasu. Limity czasu mają tylko wpływ dla wywołań systemowych wykonujących gniazda I/O (np. Odczyt (2), recvmsg (2), send (2), sendmsg (2)); limity czasu nie mają wpływu na select (2), ankiecie (2), epoll_wait (2), itp

+1

Czy przeczytałeś odpowiedź CH na to żądanie? ASIO powiela funkcjonalność systemu operacyjnego w C++, jeśli potrzebujesz więcej funkcji czasu, możesz go zaimplementować za pomocą bit-n-pieces ASIO. –

5

użyłem trochę asio docs produkować to:

class TimeoutAdjust 
{ 
public: 
    TimeoutAdjust(unsigned int dwTimeout) : m_dwTimeout(dwTimeout) {}; 

    template<class Protocol> 
    int level(const Protocol& p) const {return SOL_SOCKET;} 

    template<class Protocol> 
    int name(const Protocol& p) const {return SO_SNDTIMEO;} 

    template<class Protocol> 
    const void* data(const Protocol& p) const {return &m_dwTimeout;} 

    template<class Protocol> 
    size_t size(const Protocol& p) const {return sizeof(m_dwTimeout);} 
private: 
    unsigned int m_dwTimeout; 
}; 

Zastosowanie:

TimeoutAdjust adjust(5000); 
sSocket.set_option(adjust); 

I debugowałem go i wydaje się, że robi to, co powinien.

+1

Co czytam tutaj, że 'SO_SNDTIMEO' ma' timeval', zamiast 'unsigned int'. http://linux.die.net/man/7/socket – updogliu

+0

Ah, dokumenty MS używają DWORD dla SO_SNDTIMEO. Wygląda na to, że timeval to para długich intów, więc uważaj na czytnik. Dokumentacja MS: http://msdn.microsoft.com/en-ca/library/windows/desktop/ms740532(v=vs.85).aspx – ArtHare

+2

Po użyciu powyższego kodu otrzymuję wyjątek Wyjątek: set_option: Invalid argument.Jeśli masz jakiś kod referencyjny, proszę udostępnij to samo. – asim

Powiązane problemy