2009-08-24 10 views
0

Ich machte eine Socket-App, die Boost Asio verwendet, wie immer es scheint eine Menge CPU zu nehmen, wenn ich versuche, etwas aus dem Sockel zu lesen.Boost Asio unter 100% CPU auf Lesen

Atm i verwenden, um eine Wrapper-Klasse, so dass ich etwas so aussieht nicht haben, um die Boost-Header-Dateien in meiner Header-Datei verfügbar zu machen, die:

class SocketHandle 
{ 
public: 
    SocketHandle() 
    { 
     m_pSocket = NULL; 
     m_pService = NULL; 
    } 

    ~SocketHandle() 
    { 
     delete m_pSocket; 
     delete m_pService; 
    } 

    void connect(const char* host, const char* port) 
    { 
     if (m_pSocket || m_pService) 
      return; 

     m_pService = new boost::asio::io_service(); 

     tcp::resolver resolver(*m_pService); 
     tcp::resolver::query query(tcp::v4(), host, port); 
     tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); 
     tcp::resolver::iterator end; 

     m_pSocket = new tcp::socket(*m_pService); 

     boost::system::error_code error = boost::asio::error::host_not_found; 

     while (error && endpoint_iterator != end) 
     { 
      (*m_pSocket).close(); 
      (*m_pSocket).connect(*endpoint_iterator++, error); 
     } 

     if (error) 
      throw ... 
    } 

    tcp::socket* operator->() 
    { 
     return m_pSocket; 
    } 

private: 
    tcp::socket *m_pSocket; 
    boost::asio::io_service *m_pService; 
}; 

und dann im Lesen aus der Fassung wie folgt:

size_t recv(char *data, size_t size) 
{ 
    boost::system::error_code error; 
    size_t len = (*m_pSocket)->read_some(boost::asio::buffer(data, size), error); 

    if (error) 
       throw ... 

    return len; 
} 

Mache ich etwas falsch? Gibt es eine bessere Möglichkeit, Daten aus dem Socket zu lesen?

-Boost 1.39.0 Visual C++ Fenster

Antwort

0

Sie die enge while-Schleife vermeiden sollten:

// BAD. 
while (error && endpoint_iterator != end) 
{ 
    (*m_pSocket).close(); 
    (*m_pSocket).connect(*endpoint_iterator++, error); 
} 

Statt etwas wie versuchen:

try 
{ 
    (*m_pSocket).connect(*endpoint_iterator++, error); 
    // ... 
} 
catch (std::exception& ex) 
{ 
    // Release resources, then try connecting again. 
} 

auch diese examples an für sehen die richtigen Idiome der Verwendung von Asio.

+0

Das war von der Boost asio Beispiel: P – Lodle

+0

Aber das Problem ist mit dem Lesen nicht der Verbindungscode. – Lodle

0

Betrachten Sie die freie Funktion stattdessen verwenden,

size_t len = asio::read(*m_pSocket,asio::buffer(data, size), error); 
+0

warum? Gibt es einen Unterschied? –

1

Eine Änderung, die Sie in Erwägung ziehen wollen (und ich empfehle) ist Ihre Steckdose ruft asynchron zu machen. Auf diese Weise müssen Sie sich keine Gedanken darüber machen, dass Threads blockiert werden oder interne Socket-Anrufe sich drehen (was ich vermute, dass Sie das sehen, was Sie sehen). Stattdessen stellen Sie einfach einen Rückruf bereit, der alle Fehler und die Anzahl der empfangenen Bytes empfängt.

Es gibt viele examples in den Boost-Dokumenten, die veranschaulichen, wie dies zu tun ist, und ich habe gefunden, dass es sich zu einer viel effizienteren Verwendung von Threads und Prozessorressourcen eignet.