[c++]Multithreading

kickerxy123

Erfahrenes Mitglied
Hallo :)

ich habe ein Problem bezgl. Multithreadings.

Hier zunächst meine Daten:
-Windows XP SP3 (up-to-date)
-mingw
-dev-cpp

also ich habe hier folgenden Code:

Code:
#include <cstdlib>
#include <iostream>
#include <windows.h>
using namespace std;


static unsigned __stdcall TimerThread (PVOID pvoid); 
static HANDLE hTimerEvent = 0; 
static HANDLE hTimerThread = 0; 
int main(){
// Event erzeugen: 
hTimerEvent = CreateEvent(NULL, FALSE, TRUE, __TEXT("hTimerEvent"));  

// Thread starten 

}
// Der Thread selbst: 
static unsigned __stdcall TimerThread (PVOID pvoid)  
{ 
   while (true) 
   { 
       WaitForSingleObject(hTimerEvent, 100); //INFINITE = unendlich; in MS

       // Tu irgendwas 
     
   } 
   return 0; 
}
gut, soweit ich das verstehe ist er in einer Endlosschleife (while(true)), ist auch gut so, wartet auf ein Objekt namens hTimerEvent und zwar für 100milisekunden. Nach 100ms beginnt er dann mit seinem Code

also ist hTimerEvent Thread 1 und das unter Thread 2?

anwendung soll das ganze finden für eine Socketprogrammierung, nämlich habe ich mehrere Clienten, die alle gleichzeitig auf den Server wollen.
Dieser soll dann die Daten von den Clienten nacheinander empfangen und reagieren. Das ist auch kein Problem, aber muss auch die Reihenfolge vertauscht werden können (Threads), vgl Beispiel:

Server lauscht an Client1 mittels Funktion recv(Socket,string,0)
Client1 macht aber nichts, die Funktion wartet und kriegt gar nicht mit, dass der 2. Client was will^^

also dachte ich an multithreading..., bessere Idee=? oder könnte ihr mir hierbei helfen?

also erstmal will ich wissen ob ich alles richtig verstanden habe. dann wie ich das alles starte, denn was meint die FunktionTimer Thread mit PVOID pvoid=?

Ich hoffe mein Anliegen ist verständlich :(

ps: muss nur unter win laufen, das reicht vollkommen,

lg
eXo
 
TimerThread(hTimerEvent);

so müsste dann ja der aufruf sein.. aber wo ist jetzt mein 2.Thread


beispielshalber wäre es gut, wenn ihr mir das als beispiel macht, also

cout Thread1 dann
cout Threat2

genügt, dann kann ich weiter machen
lg
 
Nach 100ms beginnt er dann mit seinem Code
Nein, er beginnt sofort mit seiner Arbeit, da hTimerEvent sich schon im Status "signaled" befindet.

also ist hTimerEvent Thread 1 und das unter Thread 2?
"hTimerEvent" ist kein Thread, wie kommst du darauf?

Server lauscht an Client1 mittels Funktion recv(Socket,string,0)
Client1 macht aber nichts, die Funktion wartet und kriegt gar nicht mit, dass der 2. Client was will
Die Beschreibung ist nicht ganz vollständig bzw. der Ablauf nicht richtig.
Server lauscht am Socket (accept) auf Verbindungsanfragen der Clients. Dafür solltest du einen Thread einrichten.
Sobald sich Clients angemelden haben, startest du jeweils einen Thread, der sich um die Kommunikation mit immer nur einen Client kümmert.
Du hast also für jeden angemeldeten Client einen eigenen Thread. Die accept()-Geschichte könnte im Haupthread des Programms, also bei main() laufen.

TimerThread(hTimerEvent);
so müsste dann ja der aufruf sein.. aber wo ist jetzt mein 2.Thread
Der Aufruf wofür? Einen Thread startest du damit nicht. Dafür musst du entweder _beginthreadex() oder CreateThread() ausführen.

Gruß
MCoder
 
Okay danke für die Antwort.. Ich glaube da haperts bei mir an der Logik^^
also das mit accept ist okay, das hab ich im Code, auch mehrere.
Ja ich brauch für jeden Client ein Thread für die Kommunikation, okay das habe ich mir gedacht :) nur... was macht dann der Code da oben *?*

Okay, kurz gesagt: wie richte ich jetzt mehrere Threads ein?

Hier mal der ganze Ablauf bisher:
Code:
#include <windows.h>

#include <winsock2.h>

#include <stdio.h>//Prototypen
#include <iostream>
using namespace std;
int startWinsock(void);

int main()

{  
    short anzahl_spieler = 2;  //Standardeinstellung
int clients[anzahl_spieler];
unsigned short client_ID = 0;
unsigned int port = 12345; //Standardeinstellung
  long rc;

  SOCKET acceptSocket;
SOCKET connectedSocket[anzahl_spieler];
  SOCKADDR_IN addr;  // Winsock starten

  rc=startWinsock();

  if(rc!=0)

  {

    printf("Fehler: startWinsock, fehler code: %d\n",rc);

    return 1;

  }

  else

  {

    printf("Winsock gestartet!\n");

  }  // Socket erstellen

  acceptSocket=socket(AF_INET,SOCK_STREAM,0);

  if(acceptSocket==INVALID_SOCKET)

  {

    printf("Fehler: Der Socket konnte nicht erstellt werden, fehler code: %d\n",WSAGetLastError());

    return 1;

  }

  else

  {

    printf("Socket erstellt!\n");

  }
  

memset(&addr,0,sizeof(SOCKADDR_IN));

addr.sin_family=AF_INET;

addr.sin_port=htons(port);

addr.sin_addr.s_addr=ADDR_ANY;

rc=bind(acceptSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN));

if(rc==SOCKET_ERROR)

{

  printf("Fehler: bind, fehler code: %d\n",WSAGetLastError());

  return 1;

}

else

{

  cout << "Socket an port " <<port<<" gebunden\n";

}  
do{
rc=listen(acceptSocket,10);

if(rc==SOCKET_ERROR)

{

  printf("Fehler: listen, fehler code: %d\n",WSAGetLastError());

  return 1;

}

else

{

  printf("acceptSocket ist im listen Modus....\n"); 

}  


connectedSocket[client_ID]=accept(acceptSocket,NULL,NULL);

if(connectedSocket[client_ID]==INVALID_SOCKET)

{

  printf("Fehler: accept, fehler code: %d\n",WSAGetLastError());

  return 1;

}

else

{

  printf("Neue Verbindung wurde akzeptiert!\n");

  clients[client_ID] = 1;
  client_ID ++;
}

}while(client_ID < anzahl_spieler);
char buf[256];
client_ID = 0;
short verbindung = 1;
do{
rc = recv(connectedSocket[client_ID],buf,256,0);

if(rc==0 || rc==-1){
      cout <<     "Client " <<client_ID<<" hat die Verbindung unterbrochen"<<endl;
      verbindung = 9;
      } 

   client_ID ++;

}while(verbindung ==1);
      cin >> verbindung;
    return 0;

}





int startWinsock(void)

{

  WSADATA wsa;

  return WSAStartup(MAKEWORD(2,0),&wsa);

}
lg
eXo


#edit:
geht es nicht so?:
Code:
#include <cstdlib>
#include <iostream>
#include <windows.h>
using namespace std;
#include <process.h>
#include <stdio.h> 
unsigned int _stdcall ThreadFunction(void *param);
 int main(){    
     unsigned int nThreadAddress;  
       int          param = 100;    
        uintptr_t hThreadHandle = _beginthreadex( 0,  
                                                  0,
                                                  ThreadFunction,
                                                  &param,
                                                   0,
                                                   &nThreadAddress );  
WaitForSingleObject((HANDLE)hThreadHandle, INFINITE); // Wartet auf das Ende des Threads 
cout << "Thread2"<<endl;
Sleep(10000);
   return 0;
   }
     unsigned int _stdcall ThreadFunction(void *param)
     { 
                 int n = *(int *)param; 
                 
                          cout << "Thread1"<<endl;    
                             Sleep(1000);
                               return 0;
                               }
 
Zuletzt bearbeitet:
Ich habe mal schnell zusammengeschrieben, wie es aussehen könnte (keine Garantie für Fehlerfreiheit).
Der Server sollte ständig lauschen. Falls mal einer deiner Clients die Verbindung unterbricht und sich dann wieder neu verbinden will, klappt das erst wieder nach einem Server-Neustart.
Innerhalb des Threads läuft dann die Kommunikation mit der Server.

Gruß
MCoder

C++:
#include <windows.h>
#include <process.h>
#include <stdio.h> 

unsigned int _stdcall ThreadFunction(void *param);

int main()
{  
    WSADATA wsa;
    if( WSAStartup(MAKEWORD(2,0),&wsa) != 0 ) { return 1; }

    unsigned int port = 12345; //Standardeinstellung
    SOCKET acceptSocket;
    SOCKADDR_IN addr;
   
    if( (acceptSocket = socket(AF_INET,SOCK_STREAM,0) == INVALID_SOCKET ) { return 1; }

    memset(&addr,0,sizeof(SOCKADDR_IN));
    addr.sin_family=AF_INET;
    addr.sin_port=htons(port);
    addr.sin_addr.s_addr=ADDR_ANY;
    
    if( bind(acceptSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN)) == SOCKET_ERROR ) { return 1; }
    if( listen(acceptSocket,10) == SOCKET_ERROR ) { return 1; }

    while( acceptSocket != INVALID_SOCKET )
    {
        SOCKET socket = accept(acceptSocket, NULL, NULL);
    
        if( socket != INVALID_SOCKET )
        {
            unsigned int nThreadAddress;  
            uintptr_t hThreadHandle = _beginthreadex( 0,  
                                                      0,
                                                      ThreadFunction,
                                                      socket,
                                                      0,
                                                      &nThreadAddress );  
        }
    }
    
    return 0;
}

unsigned int _stdcall ThreadFunction(void *param)
{ 
    SOCKET socket = (SOCKET)param;

    while( socket != INVALID_SOCKET )
    {
        char buf[256];
        int nRead;
        
        if( (nRead = recv(socket, buf, 256, 0)) > 0 )
        {
            // Daten wurden empfangen
        }
    }
}
 
Zurück