Bad file descriptor mit boost Threads und Sockets



  • Hallo,
    ich wollte, um Boost Threads und Sockets besser zu verstehen, einen kleinen Server schreiben, der für jeden Client einen neuen Thread erzeugt und in diesem fortwähren einen Nachricht überträgt.
    Leider führt das nur zu einem Bad file descriptor, wenn ich in dem Thread auf den Socket zugreifen möchte.

    #include <iostream>
    #include <string>
    #include <boost/thread.hpp>
    #include <boost/asio.hpp>
    
    using boost::asio::ip::tcp;
    using namespace std;
    
    void handleClient(tcp::socket* socket, string* message) {
    
        if(!socket || !message)
            return;
    
        while (1) {
    
            try {
                boost::asio::write(*socket, boost::asio::buffer(*message));
            } catch (std::exception& e) {
                cerr << e.what() << std::endl;
                break;
            }
            sleep(1);
        }
    
        return;
    }
    
    int main(int argc, char* argv[]) {
        int port = 2323;
    
        if (argc > 1)
            port = atoi(argv[1]);
    
        boost::asio::io_service io_service;
    
        tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), port));
    
        cout << "Starting on " << port << endl;
    
        string message = "Hello World!\n";
    
        for (;;) {
            tcp::socket socket(io_service);
            acceptor.accept(socket);
    
    //        handleClient(&socket, &message);
            boost::thread t(handleClient, &socket, &message);
        }
    
        return 0;
    }
    


  • Das Socket wird wohl zerstört, bevor der Thread überhaupt zu laufen beginnt.


  • Administrator

    for (;;)
    { 
        tcp::socket socket(io_service); // socket wird erstellt
        acceptor.accept(socket); 
    
        boost::thread t(handleClient, &socket, &message); // thread wird gestartet
    } // socket wird zerstört -> na viel Glück, wenn der Thread dann auf das Socket zugreift
    

    Grüssli



  • Ah, danke, nun funktioniert's 🙂

    #include <iostream>
    #include <string>
    #include <boost/thread.hpp>
    #include <boost/asio.hpp>
    
    using boost::asio::ip::tcp;
    using namespace std;
    
    void handleClient(tcp::socket* socket, string* message) {
    
        if(!socket || !message)
            return;
    
        while (1) {
    
            try {
                boost::asio::write(*socket, boost::asio::buffer(*message));
            } catch (std::exception& e) {
                cerr << e.what() << std::endl;
                break;
            }
            sleep(1);
        }
    
        delete socket;
        return;
    }
    
    int main(int argc, char* argv[]) {
        int port = 2323;
    
        if (argc > 1)
            port = atoi(argv[1]);
    
        boost::asio::io_service io_service;
    
        tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), port));
    
        cout << "Starting on " << port << endl;
    
        string message = "Hello World!\n";
    
        for (;;) {
            tcp::socket* socket = new tcp::socket(io_service);
            acceptor.accept(*socket);
    
            boost::thread t(handleClient, socket, &message);
        }
    
        return 0;
    }
    

  • Administrator

    tonsiraff schrieb:

    Ah, danke, nun funktioniert's

    Nur wenn du Glück hast. Du spielst wohl gerne Russisch Roulette. Theoretisch könnten Threads weiterlaufen und der Hauptthread die main Funktion verlassen. message würde ungültig werden und du greifst noch darauf zu. Wieso übergibst du message überhaupt als Zeiger? Wieso nicht gleich als Kopie?
    Auch die Übergabe von socket als Zeiger halte ich nicht für so prickelnd. boost::asio bietet eigentlich bereits die Möglichkeit, das ganze über Threads laufen zu lassen, also mehrere Threads für mehrere Clients zu verwenden, ohne dass du solche Verrenkungen machen musst.

    Grüssli



  • ...


Log in to reply