Mehrere Threads - Anzahl: Unbekannt
-
Ich versuche hier mal mein Projekt zu schildern.
Ich habe noch nicht angefangen und will mich hier vorher eigentlich auch nur informieren.
Und zwar habe ich eine Text Datei, in jeder Zeile steht eine IP und Port, die Zeilen sind unbekannt.
Das Programm soll nun für jede Zeile einen neuen Thread starten und sich zu dieser IP verbinden
und dort in einer while Schleife in einem bestimmten Abstand ein packet hinschicken und die Antwort empfangen.
Das eigentliche Problem ist, dass es bis zu 1700 Zeilen sein können, deswegen frage ich hier besser nach,
ob ein normaler Windows Prozess überhaupt ~1700 Threads am laufen halten kann.
Sollte ich dafür CreateThread aus der WinAPI nehmen oder doch besser auf boost zurück greifen?
-
Die Threads sehe ich eigentlich nicht so als Problem, aber die Anzahl an Verbindungen ist schon recht hoch. Was für eine Anwendung soll das denn sein, wenn ich fragen darf?
-
Schonmal danke für deine Antwort.
Es werden Daten von Game Servern ausgelesen.
Das Programm würde auf nem Windows VServer laufen mit 8GB RAM und guter Internet Anbindung. Ich war mir nur nicht sicher ob man so viele Threads überhaupt erstellen kann. Das ganze soll ja noch "flüssig" laufen und keine Verbindungen sollen drunter leiden.
-
Mach es doch in "bunches", also zB. 500 Abfragen, dann gleich hinterher die nächsten 500 usw.
"Verbindung", ich nehme also an TCP?
-
Soviele Threads ist sinnlos (Context Switches / Stack). Nimm IOCP und benutze einen Threadpool.
Wenn Du mit C++ unterwegs bist kann ich Dir Boost.Asio empfehlen, welches unter Windows die IOCP kapselt und mit einer einheitlichen API zur Verfügung stellt.
-
Verwende einen Thread-Pool! Ein Thread belegt by defaultr 1 MB Callstack-Speicher; damit ist die Anzahl der Threads anhand dem physikalischen Speicher begrenzt... also unter x64 sind es logischerweise mehr als unter x86...
-
Scheint nicht ganz so einfach zu sein.
Finde im Internet auch nur viel zu .NET, dabei will ich auf Managed C++ verzichten.
Ist dieser link http://threadpool.sourceforge.net in Ordnung für mein Vorhaben?
Kenn mich in dem Gebiet echt noch nicht aus.
-
Guck Dir doch meinen Post an.
-
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.