WaitForMultipleObjects mit Vector als 2. Argument?



  • Guten Tag. Ich bin Anfänger in C++ und wage mich gerade an einen multithreaded-Server. Bis jetzt funktioniert das auch alles ganz gut, aber leider akzeptiert die Funktion WaitForMultipleObjects keine Vektoren als Pointer. Ich habe es zwar über ein bisschen tricksen geschafft das der Compiler es kompilliert, aber trotzdem gibt es keinen Rückgabewert, wenn ein Thread geschlossen wird.
    Ich möchte anhand dieser Funktion feststellen, ob ein Thread geschlossen wurde und dann entsprechend reagieren.

    #include <iostream>
    #include <winsock2.h>
    #include <windows.h>
    #include <vector>
    //#pragma comment(lib, "libws2_32.lib" ) <--nützt nichts
    
    using namespace std;
    
    ///Prototypen
    void printDebug(const char*,int);
    void printDebug(const char*, int, int);
    
    class myClient
    {
        public:
            SOCKET ClientSocket;
            char recvBuffer[257];
            myClient()
            {
                memset(recvBuffer, 0, 257);
            }
        private:
    };
    
    class myServer
    {
        public:
            myServer();
            int OnExecute();
        private:
            friend DWORD WINAPI ClientRoutine(myServer*);
            //====>wichtiger Kram
            CRITICAL_SECTION ServerCritical;
            unsigned int MAX_NUMBER_CLIENTS;
            unsigned int numberOfClients;
            int ServerPort;
            SOCKET acceptSocket;
            vector<HANDLE> aThreadsofClients;
            vector<myClient> aClients;
            //====>unwichtiger Kram
            timeval TIMEOUT_0;
            char recvBufferServer[257];
            int rc_class; //rückgabewert
            SOCKADDR_IN addrsocket;
            FD_SET fd;
            void parseClientData(unsigned int indexOfClient);
            void ClientRecv(int indexOfClient);
            void CloseConnection(unsigned int indexOfSocket);
            void AcceptNewSocket();
            int StartupWinsock();
            void CleanupWinsock();
            WSADATA wsaD;
    };
    
    myServer::myServer()
    {
        //==>timeout definieren
        TIMEOUT_0.tv_sec = 0;
        TIMEOUT_0.tv_usec = 0;
        //kritischen Bereich definieren
        InitializeCriticalSection(&ServerCritical);
        //Arrays nullen
        memset(recvBufferServer, 0, sizeof(recvBufferServer));
        MAX_NUMBER_CLIENTS = 64;
        ServerPort = 1337; //Port festlegen
        numberOfClients = 0;
        ///======================>Start Winsock
        StartupWinsock();
        if ((acceptSocket = socket(AF_INET, SOCK_STREAM, 0))==INVALID_SOCKET)
        {
            printDebug("ERROR - acceptSocket konnte nicht erstellt werden. Fehler Nr.", WSAGetLastError(), __LINE__);
        }
        ///===========>Socket binden
        memset(&addrsocket, 0, sizeof(SOCKADDR_IN)); //alles nullen
        addrsocket.sin_port = htons(ServerPort);
        addrsocket.sin_family = AF_INET;
        addrsocket.sin_addr.s_addr = INADDR_ANY;
        if ((bind(acceptSocket, (SOCKADDR*)&addrsocket, sizeof(SOCKADDR_IN)))==SOCKET_ERROR)
        {
            printDebug("ERROR - Binden des Sockets Fehler Nr.", WSAGetLastError(), __LINE__);
        }
        if ((listen(acceptSocket, MAX_NUMBER_CLIENTS))==SOCKET_ERROR)
        {
            printDebug("ERROR at listen Fehler Nr.", WSAGetLastError(), __LINE__);
        }
        else
        {
            printDebug("[SUCCES] acceptSocket wurde erfolgreich gebunden! Maximale Verbindungen:", MAX_NUMBER_CLIENTS, __LINE__);
            printDebug("Port Nr.", ServerPort, __LINE__);
        }
    
    }
    
    int myServer::OnExecute()
    {
        unsigned int rc_Threads = WAIT_TIMEOUT;
        while (1)
        {
            ///=============>Verbindungen annehmen
            AcceptNewSocket(); //acceptSocket überprüfen
            ///==============>Verbindungen trennen
            rc_Threads = WaitForMultipleObjects(aThreadsofClients.size(), &aThreadsofClients[0], false, 0);
            if (rc_Threads != WAIT_TIMEOUT && rc_Threads != WAIT_FAILED)
            {
                printDebug("Client wird getrennt Nr. ", rc_Threads, __LINE__);
                CloseConnection(rc_Threads);
            }
        }
        return 0;
    }
    
    void myServer::parseClientData(unsigned int indexOfClient)
    {
        cout << aClients.at(indexOfClient).recvBuffer << endl; //BufferOverflow oder irgendwas anderes
        return;
    }
    
    void myServer::CloseConnection(unsigned int indexOfSocket)
    {
        CloseHandle(aThreadsofClients[indexOfSocket]);
        aThreadsofClients.erase(aThreadsofClients.begin()+indexOfSocket);
        closesocket(aClients[indexOfSocket].ClientSocket);
        aClients.erase(aClients.begin()+indexOfSocket); //ClientObject aus dem Vector löschen
        numberOfClients--;
        return;
    }
    
    DWORD WINAPI ClientRoutine(myServer* thisServer)
    {
        printDebug("ClientThread Nr. ", thisServer->numberOfClients, __LINE__);
        return 0;
    }
    
    void myServer::AcceptNewSocket()
    {
        FD_ZERO(&fd);
        FD_SET(acceptSocket, &fd);
        if (select(0, &fd, 0, 0, &TIMEOUT_0)==SOCKET_ERROR) //kontrolliert kurz dem acceptSocket
        {
            printDebug("ERROR - Select Fehler", WSAGetLastError(), __LINE__);
        }
        if (FD_ISSET(acceptSocket, &fd))
        {
            aClients.resize(numberOfClients+1);
            aClients.at(numberOfClients).ClientSocket = accept(acceptSocket, NULL, NULL); //Verbindung annehmen
            printDebug("Neue Verbindung angenommen! Client Nummer:", numberOfClients, __LINE__);
            aThreadsofClients.resize(numberOfClients+1);
            CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ClientRoutine, (LPVOID)this, NULL, (LPDWORD)&aThreadsofClients[numberOfClients]);
            numberOfClients++;
        }
        return;
    }
    
    int myServer::StartupWinsock()
    {
        return WSAStartup(MAKEWORD(2,0), &wsaD);
    }
    
    void myServer::CleanupWinsock()
    {
        return;
    }
    
    void printDebug(const char *msg, int zeilennummer)
    {
        cout << "[DEBUG] in line " << zeilennummer << ": " << msg << endl;
    }
    
    void printDebug(const char *msg, int zahl, int zeilennummer)
    {
        cout << "[DEBUG] in line " << zeilennummer << ": " << msg << " " << zahl << endl;
    }
    
    int main()
    {
        printDebug("Starting Server...", __LINE__);
        myServer obj;
        obj.OnExecute();
        return 0;
    }
    


  • Sorry, der Fehler liegt in Zeile 103. Die Funktion in der If-Konstruktion springt einfach nicht an. Mein Compiler ist CodeBlock's minGW. Danke für euer Verständniss^^



  • Sry bin selbst Anfänger hab aber das gleiche Problem...



  • Wenn ich mit GetLastError() überprüfe, kriege ich den Code 6. Dies bedeutet anscheinend: ERROR_INVALID_HANDLE.
    Leider weiss ich nicht, wie man das Problem lösen könnte. Naja, ich könnte zwar WaitForSIngleObjects warten, aber in diesem Kontext wäre das mehr als unelegant 😉



  • Hab jetzt nur das Relevante gecheckt, zum Rest sag ich mal nichts...

    http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453

    Letzter Parameter: A pointer to a variable that receives the thread identifier.

    Rückgabewert: If the function succeeds, the return value is a handle to the new thread.

    Klar?



  • Dankeschön 🙂
    Da war der Typcast wohl eher eine negative Idee.



  • Du castest überhaupt viel zu oft.
    Wenn du ClientRoutine die richtige Signatur verpasst, musst du bei der Übergabe der Thread-Funktion z.B. auch nimmer casten.



  • WinsockWannabe schrieb:

    Dankeschön 🙂
    Da war der Typcast wohl eher eine negative Idee.

    Du solltes nur casten wenn nötig...


Anmelden zum Antworten