Mehrere Threads - Anzahl: Unbekannt



  • So, ich grab den Thread nochmal aus, da ich keine Lust habe nen neuen aufzumachen.
    Handelt sich immer noch um das selbe Projekt, doch jetzt sind es nur knapp 7 IPs in der Text Datei, somit hatte ich vor CreateThread zu verwenden und 7 Threads zu starten.
    Das ganze funktioniert insofern das wirklich 7 Threads gestartet werden, doch immer nur der letzte Thread aktiv über send() Daten zum Server schickt(Habe es mit WPE Pro gesnifft!). Das Programm scchickt also nur immer zu der letzten IP die in der Textdatei steht das packet. Die ersten 6 Threads scheinen nicht zu laufen.
    Hier kurzer Ausschnitt von den wichtigen Sachen:

    typedef struct MyData
    {
    	char *cGlobalIP;
    	char *cGlobalPort;
    }MYDATA, *PMYDATA;
    
    int main(int argc, char *argv[])
    {
    	PMYDATA	pDataArray[7];
    	DWORD   dwThreadIdArray[7];
        HANDLE  hThreadArray[7]; 
    
    	char cServer[MAX_PATH];
    	fstream fServer;
    	fServer.open(argv[1], ios::in);
    	while(!fServer.eof())
    	{
    		//String teilen
    		fServer.getline(cServer, sizeof(cServer));
    		/*
    		...
    		Hier wird nur IP vom Port getrennt. 
    		cIP ist die IP und cPort der Port. :)
    		*/
    
    		//Thread erstellen
    		int i = 0;
    		pDataArray[i] = (PMYDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYDATA));
    
    		pDataArray[i]->cGlobalIP = cIP;
    		pDataArray[i]->cGlobalPort = cPort;
    
    		hThreadArray[i] = CreateThread(NULL, 0, Server, pDataArray[i], 0, &dwThreadIdArray[i]);
    		i++;
    	}
    	fServer.close();
    
    	cout << GetLastError() << endl;
    	system("PAUSE");
    	//Threads beenden und Speicher freigeben
    	return 0;
    }
    
    DWORD WINAPI Server(LPVOID lpParam)
    {
    	PMYDATA pDataArray = (PMYDATA)lpParam;
    
    	int nResult;
    	WSADATA wsaData;
    	SOCKET ConnectSocket;
    	struct sockaddr_in clientService;
    
    	nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    	if(nResult != NO_ERROR)
    	{
    		return 0;
    	}
    
    	ConnectSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    	if(ConnectSocket == INVALID_SOCKET)
    	{
    		return 0;
    	}
    
    	clientService.sin_family = AF_INET;
    	clientService.sin_addr.s_addr = inet_addr(pDataArray->cGlobalIP);
    	clientService.sin_port = htons(atoi(pDataArray->cGlobalPort));
    
    	nResult = connect(ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService));
    	if(nResult == SOCKET_ERROR)
    	{
    		return 0;
    	}
    
    	while(1)
    	{
    		//blablabla :D
    	}
    	return 1;
    }
    


  • Auf die Schnelle:

    C und C++ mischen == hässlich (true)
    WSAStartup nur 1x aufrufen
    struct initialisieren: sockaddr_in clientService = { };
    besser kein connect() bei UDP, sondern einfach nur sendto/recvfrom
    sämtliche rückgabewerte prüfen und checken was falsch läuft



  • Danke schonmal für deine Antwort, ich habe versucht all deine Tipps zu befolgen, doch das Problem besteht weiter hin.
    Soweit bin ich schon... Doch es wird tatsächlich nur der letzte Server abgefragt, somit frag ich mich was die anderen Threads machen?

    typedef struct MyData
    {
        char *cGlobalIP;
        char *cGlobalPort;
    }MYDATA, *PMYDATA;
    
    int main(int argc, char *argv[])
    {
        int nResult;
        WSADATA wsaData;
    	nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
        if(nResult != NO_ERROR)
        {
            cout << "WSAStartup: " << WSAGetLastError() << endl;
    		system("PAUSE");
    		return 0;
        }
    
    	PMYDATA    pDataArray[7];
        DWORD   dwThreadIdArray[7];
        HANDLE  hThreadArray[7];
    
        char cServer[MAX_PATH];
        fstream fServer;
        fServer.open(argv[1], ios::in);
        while(!fServer.eof())
        {
            //String teilen
            fServer.getline(cServer, sizeof(cServer));
            /*
            ...
            Hier wird nur IP vom Port getrennt.
            cIP ist die IP und cPort der Port. :)
            */
    
            //Thread erstellen
            int i = 0;
            pDataArray[i] = (PMYDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYDATA));
    
            pDataArray[i]->cGlobalIP = cIP;
            pDataArray[i]->cGlobalPort = cPort;
    
            hThreadArray[i] = CreateThread(NULL, 0, Server, pDataArray[i], 0, &dwThreadIdArray[i]);
            i++;
        }
        fServer.close();
    
        cout << GetLastError() << endl;
        system("PAUSE");
        //Threads beenden und Speicher freigeben
        return 0;
    }
    
    DWORD WINAPI Server(LPVOID lpParam)
    {
        PMYDATA pDataArray = (PMYDATA)lpParam;
    
        SOCKET ConnectSocket;
        struct sockaddr_in clientService = {};
    
    	ConnectSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if(ConnectSocket == INVALID_SOCKET)
        {
            return 0;
        }
    
        clientService.sin_family = AF_INET;
        clientService.sin_addr.s_addr = inet_addr(pDataArray->cGlobalIP);
        clientService.sin_port = htons(atoi(pDataArray->cGlobalPort));
    
    	const char *szQuery = "\xff\xff\xff\xff" "\x02" "getstatus.";
        while(1)
        {
    		sendto(ConnectSocket, szQuery, strlen(szQuery), 0, (SOCKADDR *)&clientService, sizeof(clientService));
            //blablabla :D
        }
        return 1;
    }
    


  • Habe jetzt mehr oder weniger herausgefunden das sich alle 7 Threads um die selbe(letzte) IP kümmern... schon sehr komisch.. ich übergebe dem jeweiligen Thread doch einmalige Daten.



  • Dann zeig mal den gesamten Code in "while(!fServer.eof())".



  • In der Text Datei liegt die IP und der Port in diesem Format: "IP:PORT" vor, jeweils pro Zeile.
    Hier ist der Ausschnitt zum splitten(eher noch provisorisch klappt aber ohne Probleme):

    while(!fServer.eof())
    {
    	//String teilen
    	fServer.getline(cServer, sizeof(cServer));
    	string szServer = cServer;		
    	int nColon = szServer.find(":");
    
    	size_t nIP;
    	size_t nPort;
    	char cIP[50];
    	char cPort[20];
    
    	nIP = szServer.copy(cIP, nColon, 0);
    	cIP[nIP] = '\0';
    
    	nPort = szServer.copy(cPort, szServer.length(), nColon + 1);
    	cPort[nPort] = '\0';
    
    	//Thread erstellen
    	int i = 0;
    	pDataArray[i] = (PMYDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYDATA));
    
    	pDataArray[i]->cGlobalIP = cIP;
    	pDataArray[i]->cGlobalPort = cPort;
    
    	hThreadArray[i] = CreateThread(NULL, 0, Server, pDataArray[i], 0, &dwThreadIdArray[i]);
    
    	i++;
    }
    


  • Die Variablen cIP/cPort leben bis zum Ende des Blocks, beim nächsten while-Durchlauf sind sie nicht existent. Du greifst danach aber per Zeiger drauf zu. Nur Glück, dass das "gut" geht...



  • Mh, das verwirrt mich etwas^^
    Hab mich an dem Beispiel aus der MSDN gehalten in dem der Abschnitt mit den Zeigern(pDataArray[i]->cGlobalIP = cIP;) so kommentiert wird: "// Generate unique data for each thread to work with.".
    Wie kann ich jedem einzelnen Thread denn sonnst einmalige Daten übergeben?...
    Komm echt nich weiter...



  • Du musst doch nur dafür sorgen, dass deine Strings so lange leben, wie du sie benutzt.

    Hab mal aufgeräumt. Minimal ftw 😃

    // Ungetestet/Unkompiliert und ohne Überprüfungen :D
    
    // u.A.
    #include <process.h>
    #include <string>
    
    struct MyData
    {
    	std::string ip;
    	std::string port;
    };
    
    unsigned int __stdcall ServerThread(void* param)
    {
        MyData* myData = (MyData*)param;
    
    	// Daten gültig
    
    	delete myData;
    
    	return 0;
    }
    
    int main(int argc, char** argv)
    {
    	WSADATA wsaData;
    	WSAStartup(MAKEWORD(2,2), &wsaData);
    
    	std::ifstream file(argv[1]);
    	std::string row;
    
    	while(std::getline(file, row))
    	{
    		unsigned int pos = row.find(":");
    
    		MyData* myData = new MyData;
    
    		myData->ip = row.substr(0, pos);
    		myData->port = row.substr(pos + 1);
    
    		_beginthreadex(0, 0, ServerThread, myData, 0, 0); // CreateThread() hat ein leak
    	}
    
    	file.close();
    
    	std::cin.get(); // Whatever
    }
    


  • Danke funktioniert perfekt! 😃
    Werd mich wohl doch besser noch mit Threads aus einander setzen müssen. 🙂


Anmelden zum Antworten