2016-05-23 5 views
1

Die for-Schleife in main.cpp, die eine Funktion aufruft, die boost :: mutex verwendet und die mit read_until aus einem Socket liest, wird nur einmal ausgeführt, danach ist es wie blockiert. Ich habe versucht, eine Fortsetzung vor den schließenden Klammern zu setzen und dann stürzt es ab. Es hängt wahrscheinlich mit Threading zusammen. input stream error aufgrund der Serialisierung Input/Output: ein Fehler passiertBoost.Asio-Socket wird blockiert

// MAIN.CPP 

int main(int argc, char* argv[]) 
{ 
    std::cout << "Enter port number: "; 
    std::string port; 
    std::getline(std::cin, port); 
    int tempPort = std::stoi(port); 
    Network * network = new Network(tempPort); 

    int it = 0; 
    boost::thread * t1; 
    t1 = new boost::thread([&network, &it] 
    { 
     while (true) 
     { 
      boost::asio::ip::tcp::socket * sock = new boost::asio::ip::tcp::socket(network->io_service); 
      network->accept(*sock); 

      if (network->socketList.size() > 0) 
      { 
       for (boost::asio::ip::tcp::socket * s : network->socketList) 
       { 
        if (s->remote_endpoint().address().to_string() == sock->remote_endpoint().address().to_string()) 
        { 
         continue; 
        } 
        else { 
         network->socketList.push_back(sock); 
         std::cout << s->remote_endpoint().address().to_string() << " connected." << std::endl; 
        } 
       } 
      } 
      else { 
       network->socketList.push_back(sock); 
       std::cout << sock->remote_endpoint().address().to_string() << " connected." << std::endl; 
      } 
     } 
    }); 

    while (true) 
    { 
     for (boost::asio::ip::tcp::socket * sock : network->socketList) 
     { 
      std::cout << "on range-based for loop" << std::endl; 
      network->readChatMessage(*(sock)); 
     } 
    } 
    t1->join(); 

    return 0; 
} 

// NETWORK.CPP 
int Network::sendChatMessage(boost::asio::ip::tcp::socket & socket, ChatMessage & message) 
{ 
    try 
    { 
     boost::system::error_code err; 

     boost::asio::streambuf buf; 
     { 
      std::ostream out(&buf); 
      boost::archive::text_oarchive oa(out); 
      oa & message; 

      std::cout << std::string(message.text.begin(), message.text.end()) << std::endl; 
     } 

     m.lock(); 
     write(socket, buf, err); 

     if (err) 
     { 
      std::cout << err.message() << std::endl; 
     } 

     m.unlock(); 

     std::cout << "Mensagem enviada com sucesso!" << std::endl; 
    } 
    catch (std::exception& e) 
    { 
     std::cout << e.what() << std::endl; 
    } 

    return 0; 
} 

int Network::readChatMessage(boost::asio::ip::tcp::socket & socket) 
{ 
    std::cout << "in readChatMessage()" << std::endl; 

    boost::system::error_code err; 

    boost::asio::streambuf buf; 

    m.lock(); 
    boost::asio::read_until(socket, buf, '\0', err); 

    if (err) 
    { 
     std::cout << err.message() << std::endl; 
    } 

    m.unlock(); 

    std::istream in(&buf); 
    ChatMessage message; 

    boost::archive::text_iarchive ia(in); 
    ia & message; 

    std::cout << std::string(message.text.begin(), message.text.end()) << std::endl; 
    this->sendChatMessage(socket, message); 

    return 0; 
} 
+1

I 6 Minuten verbracht haben versucht, eine Teilmenge des Programms, um herauszufinden, die abgeschlossen ist. Kannst du es SSCCE machen? Warum benutzt alles "neu"? – sehe

+0

Dies ist möglicherweise nicht verwandt, aber es scheint mir, dass Ihr Programm nie beenden wird - Sie beitreten den Thread, aber ich sehe keine Möglichkeit, wie die Thread-Funktion beenden kann (nett, wie in nicht mit einigen nicht abgefangenen Ausnahme). –

+0

+1 auf die Frage nach "neu". Wenn Sie Objekte dynamisch zuweisen müssen, warum sollten Sie nicht zumindest intelligente Zeiger verwenden? Dies verlangt nur nach Speicherlecks aus keinem guten Grund. | Wenn es abstürzt, wo? Verwenden Sie Debugger, um mehr zu finden. | Warum versuchen Sie in 'readChatMessage' die Nachricht zu deserialisieren und zu verarbeiten, wenn das Lesen fehlschlägt? | 'scoped_lock' oder etwas ähnliches könnte auch nützlich sein. Verwende RAII. –

Antwort

0

ich in der Lage war, das Problem nach dem Debuggen zu beheben und Bearbeiten dem Code ein wenig, dann war ich in der Lage, dort zu sehen war. Ich habe den Fehler richtig behandelt, den Mutex entsperrt, als der Fehler auftrat, und den Mutex nicht ungeschehen gemacht.

Snippet:

int Network::readChatMessage(boost::asio::ip::tcp::socket & socket) 
{ 
    std::cout << "in readChatMessage()" << std::endl; 

    boost::system::error_code err; 

    boost::asio::streambuf buf; 

    m.lock(); 
    boost::asio::read_until(socket, buf, '\0', err); 

    if (err) 
    { 
     m.unlock(); 
     std::cout << err.message() << std::endl; 
     return 0; 
    } 
    else { 

     m.unlock(); 

     std::istream in(&buf); 
     ChatMessage message; 

     boost::archive::text_iarchive ia(in); 
     ia & message; 

     std::cout << std::string(message.text.begin(), message.text.end()) << std::endl; 
     this->sendChatMessage(socket, message); 
     return 0; 
    } 
    m.unlock(); 

    return 0; 
} 
+0

Als zukünftige Referenz sollten Sie entweder einen ['lock_guard'] (http://en.cppreference.com/w/cpp/thread/lock_guard) (STL/C++ 11) oder einen [' scoped_lock' verwenden ] (http://www.boost.org/doc/libs/1_61_0/doc/html/boost/interprocess/scoped_lock.html) (boost) um mit deinen Mutexen umzugehen, da es dieses Problem in erster Linie verhindert hätte Du hast es getan. – Xirema

+0

@Xirema Danke, das hat sehr gut funktioniert, und es hat einen Absturz verursacht, als viele Nachrichten gleichzeitig gesendet wurden! :) –