2012-03-28 5 views
1

Ich versuche, ein Timeout für eine Boost.Asio lesen auf einem TCP-Socket zu implementieren.Boost.Asio Deadline_timer funktioniert nicht wie erwartet

Ich versuche eine async_read_some mit einer deadline_timer zu verwenden. Meine Funktion unten ist ein Mitglied einer Klasse, die einen Smart-Zeiger auf den TCP-Socket und io_service enthält. Was ich würde erwarten, dass passieren, wenn auf einem aktiven Socket aufgerufen, der keine Daten zurückgibt 2 Sekunden warten und falsche zurückgeben.

Was passiert ist: Wenn der Socket keine Daten zurückgibt, funktioniert es wie erwartet. Wie auch immer, wenn der Server die Daten zurückgibt, die das Verfahren zu der unten beschriebenen Methode aufruft, kehrt er sofort zurück, weil zu den Zeitgebern ein Rückruf aufgerufen wird, ohne die zwei Sekunden zu warten.

Ich habe versucht, die async_read_some Aufruf kommentieren und die Funktion funktioniert immer wie erwartet. Warum sollte async_read_some ändern, wie der Timer funktioniert?

client::client() { 
     // Init socket and timer 
     pSock = boost::shared_ptr<tcp::socket > (new tcp::socket(io_service)); 
    } 

bool client::getData() { 

       // Reset io_service 
       io_service.reset(); 

       // Init read timer 
       boost::asio::deadline_timer timer(pSock->io_service()); 
       timer.expires_from_now(boost::posix_time::seconds(2)); 
       timer.async_wait(boost::bind(&client::read_timeout, this, boost::system::error_code(), true)); 


    //   // Async read the data 
       pSock->async_read_some(boost::asio::buffer(buffer_), 
         boost::bind(&client::read_complete, 
         this, 
         boost::asio::placeholders::error, 
         boost::asio::placeholders::bytes_transferred 
         )); 



       // While io_service runs check read result 
       while (pSock->io_service().run_one()) { 
        if (m_read_result > 0) { 
         // Read success 
         return m_read_result; 
        }else if(m_read_result < 0){ 
         return false; 
        } 
       } 
      } 
} 



void client::read_complete(const boost::system::error_code& error, size_t bytes_transferred) { 
    if (!error) { 
     m_read_result = bytes_transferred; 
    }else{ 
     m_read_result = -1; 
    } 
} 

void client::read_timeout(const boost::system::error_code& error, bool timeout) { 
    if(!error){ 
     m_read_result = -1; 
    } 
} 
+0

Könnten Sie die komplette bieten zu _1 oder einen Fehler :: Platzhalter geändert werden (und es wäre, wenn minimal gut sein) Quellcode? Meine vorherige Antwort war leider falsch. –

+0

Async-Handler-Code hinzugefügt –

+0

Sie setzen 'read_complete' auf' bytes_transfered', wenn es sich um einen Fehler handelt, und '-1', wenn kein Fehler vorliegt. Ist das richtig? –

Antwort

1

Einfaches Problem, wenn die Timer-Boost-Einrichtung :: system :: error_code() sollte

timer.async_wait(boost::bind(&client::read_timeout, this, _1, true)); 
0

Sie haben Bedingung negiert, wenn Sie für einen Verbindungsfehler überprüfen.

es sein sollte:

if(error){ 
    std::cout << "read_timeout Error - " << error.message() << std::endl; 
} 

Nun sehen Sie, dass der Rückruf mit dem Fehlercode boost::asio::error::operation_aborted aufgerufen wird.

Dies ist, weil, wenn Sie Daten erhalten, Sie von Funktion getData und deadline_timer Destruktor zurückrufen ruft den Rückruf mit dem Fehlercode festgelegt.

+0

Ich überprüfe Fehlercodes in meinem Timeout-Handler, sie werden immer mit Erfolg aufgerufen. –

+0

Ich habe den Code bearbeitet, dasselbe Problem. deadline_timer wird erst aufgebaut, nachdem ich das vorzeitige Feuer des Timeouts bereits erhalten habe. –

Verwandte Themen