Milti-threading : Mutex

Status
Niet open voor verdere reacties.

Xabre

Gebruiker
Lid geworden
22 sep 2007
Berichten
55
Hoi,


Ik heb een DB-Server gemaakt, wat er gebeurt is volgende :
- Server wacht op client
- Client start op en maakt een verbinding met de server
- de server maakt een nieuwe thread aan en begint opnieuw te wachten op een volgende client
- de clientthread zoekt onneindig op een commando van de client (tot deze afsluit)
- een commando is een globale DB klasse aanroepen, gegevens uithalen en deze verzenden naar de client, via de client thread

Wat er nu gebeurt is, als er meerder gebruikers opzitten, en deze query's zenden dat de DB klasse verschillende malen wordt gebruikt op hetzelfde moment. Dit kan echter niet, wat leidt tot een fout! Ik heb gevonden dat ik dit probleem kan oplossen door een mutex te
gebruiken die 1 thread per keer toegang verleent tot de klasse DB. Ik heb dan volgende gedaan :

Code:
class       SCLIENT
{
            SOCKET   ClientSocket;                   
            
            friend DWORD WINAPI ClientThread( void * pParam )
            {                       
                  SCLIENT *temp = (SCLIENT *)pParam;
                  temp->Buffer = "";
                  
                  while ( !temp->DeadlyIdleClient )
                  {
                        Sleep(100);
                        
                        if( temp->Buffer == "" )
                        {   
                            temp->ReceiveData();
                            //Error("Receiving!");
                        }
                        else
                        {                     
                            temp->DoAsk("");
                            temp->Buffer = "";                            
                        }
                  }
                   
                  return 0;
            }
                        
            public:
                   bool Init(SOCKET   SSocket )
                   {
                           IWantMore = false;
                          
                          if( listen( SSocket,65536 ) == 0 )
                          {
                              IWantMore = true;
                          }
                        
                          ClientSocket = accept( SSocket, NULL, NULL );
                          
                          if (ClientSocket == INVALID_SOCKET) {	        	
	                 	       Disconnect();
	           	               return WSAGetLastError();
                          }   
                          
                          ClientHandle = CreateThread( NULL, 0,ClientThread, (void *)this, 0, NULL);
                          
                          Mutex = CreateMutex( 
                          NULL,              // default security attributes
                          FALSE,             // initially not owned
                          NULL);
                          
                          return true;                         
                                      
                   }
                   
                   HANDLE   ClientHandle;
                   HANDLE   Mutex;
                   
                   bool     IWantMore;   //Word gebruikt om te bepalen of er een nieuwe client thread zal moeten worden gemaakt
                   
                   char     *Buffer;     //De buffer waarin zowel inkomende als uitgaande berichten worden opgeslagen
                   
                   char     *DoAsk(char *command);     //Commando functie
                   
                   bool     SaveToErrorlog(char *str);
                   bool     SaveToServerlog(char *str);
                   
                   bool     Disconnect();
            
                   bool     SendData();
                   bool     ReceiveData();
};

...

char        *SCLIENT :: DoAsk(char *command = "")
{            
            vector <string> cmd;
            cmd = Explode(command == "" ? Buffer : command," ");
            
            if( cmd.size() == 0 )
                return "";
            
            if( cmd.at(0) == "CLOSECON" )
            {                
                Disconnect();
                cmd.clear();
                return "[LOG] Disconnected!\n";
            }
            else if( cmd.at(0) == "GET" )
            {    
                     long dwWaitResult = WaitForSingleObject( 
                     Mutex,    // handle to mutex
                     INFINITE);
                 
                 if( dwWaitResult == WAIT_OBJECT_0 )
                 {    
                     string RetValue;                     
                 
                     FILE *ParseFile;
                     long size;
                     long readBytes;
                 
                     Replace(cmd[1],"%20"," ");
                 
                     ParseFile = fopen( (char *)(cmd.at(1) == "/" ? "./index.html" : ("." + cmd.at(1) ).c_str()), "rb" );
                     if( ParseFile != NULL )
                     {
                         fseek (ParseFile, 0, SEEK_END);
                         size = ftell (ParseFile);
                         fseek(ParseFile, 0, SEEK_SET);
                 
                         string buf = "HTTP/1.1 200 OK\r\nAccept-Encoding: deflate\r\nServer: DBkeep 3 - Internal Server\r\nContent-Length: ";
                         buf += size;
                         buf += "\r\nContent Type: text/plain; charset=UTF-8\r\nConnection: close\r\n\r\n";
                 
                         Buffer = (char *)buf.c_str();
                         if( SendData() == -1)
                             return NULL;  
                 
                         Buffer = new char[65536];
                         
                 
                         while ( size ) {
                             readBytes = fread(Buffer, 1, ((size > 65536) ? 65536 : size), ParseFile);
                             if( send(ClientSocket, Buffer, readBytes, 0) == -1 )
                                 break; 
                              
                             size-=readBytes;
                             
                             Sleep(1);
                         }
                 
                         fclose(ParseFile);
                         delete ParseFile;
                         delete Buffer;
                         
                         RetValue = "[LOG] User succesfully got :";
                         RetValue += cmd.at(1) == "/" ? "./index.html" : ("." + cmd.at(1) ).c_str();
                         RetValue += "\n"; 
                         
                         SendMessageToHost( (char *)RetValue.c_str() );
                         
                         SaveToServerlog( (char *)RetValue.c_str() );            
                     }
                     else
                     {
                         Buffer = "HTTP/1.1 404 Not Found\r\nContent-Length: 14\r\nContent-Type: text/plain\r\n\r\nFile not found";                     
                         SendData();
                         
                         RetValue = "[ERROR] Couldn't handle :";
                         RetValue += cmd.at(1) == "/" ? "./index.html" : ("." + cmd.at(1) ).c_str();
                         RetValue += " [File doesn't exist]\n";
                         
                         SendMessageToHost( (char *)RetValue.c_str() );                         
                         SaveToErrorlog( (char *)RetValue.c_str() );
                     }
                     
                     Disconnect();
                     cmd.clear();
                     
                     ReleaseMutex(Mutex);
                     
                     return (char *)RetValue.c_str();
               }
            }
            else if( cmd.at(0) == "DB_REQUEST" )
            {    
                     long dwWaitResult = WaitForSingleObject( 
                     Mutex,    // handle to mutex
                     INFINITE);
                 
                 if( dwWaitResult == WAIT_OBJECT_0 )
                 {             
                 string ID = DB->Connect( cmd.at(1),cmd.at(2) );
             
                 if( ID == "ILLIGAL_ATTEMPT" )
                 {  
                    string RetValue = "\n[ERROR] ILLIGAL ATTEMPT TO ACCES DB-SERVER : " + cmd.at(1) + "@" + cmd.at(2);
                     
                    SendMessageToHost( (char *)RetValue.c_str() );
                    cmd.clear();
                    
                    return "HALT";
                 }
                 SendMessageToHost( (char *)("\n[LOG] DB-Server : " + cmd.at(1) + " has logged in!").c_str() );

                 vector <string> Requests = Explode(command == "" ? Buffer : command,"<=>");
                 
                 if( Requests.size() > 1 )
                 {                 
                     vector <string> Query = DB->Command(ID, Requests.at(1) );
                 
                     for(int i = 0;i < Query.size();i++)
                     {
                         Buffer = (char *)(Query.at(i) + "\n").c_str();
                         SendData();                      
                     }                 
                 }
                 else
                 {
                     Buffer = "NO_CORRECT_REQUEST : Please ask your software distributor for solutions";
                     SendData();
                 }
                 
                 Requests.clear();
                 ReleaseMutex(Mutex);
                 }
            }
            
            cmd.clear();
            
            return "";
}

Simpel gezegd :
commando functie opent
WaitForSingleObject(...);
klasse DB staat vrij, ok ga door met de functie
Verwijder de mutex

Heeft iemand ervaring hiermee? gelieve mij te zeggen wat ik fout doe. Dank bij voorbaat!
 
Laatst bewerkt:
Ik heb ook nero7, maar voor Dual Layer gebruik ik ImgBurn om deze te branden.
 
Ik heb ook nero7, maar voor Dual Layer gebruik ik ImgBurn om deze te branden.
Humpe,
lees eerst goed de vraag door. Plaats daarna pas je antwoordt. Jou antwoordt heeft hier niks mee te maken. Kijk eventueel eerst goed in welke sectie de vraag staat. De sectie C++ heeft niets met branden of brandsoftware te maken.
 
Laatst bewerkt:
sorry, ik heb deze sit bij de verkeerde site geplaatst.
 
CreateMutex maakt nu iedere keer een nieuw Mutexobject.
Je kan dit voorkomen door er een naam aan te geven.


Mutex = CreateMutex( NULL, FALSE, "SCLIENT");

Je kan ook CreateMutex gewoon 1 keer aanroepen en met 1 hendel werken. Een naam voor de mutex is dan niet nodig. Als je de hendel onderdeel van de klasse wil laten moet hij wel static zijn.

if(Mutex==0)Mutex=CreateMutex(NULL,FALSE,0);

In de functie DoAsk staat de conditie command=="". Dit kan een probleem zijn daar command van het type char* is en niet van de c++ klasse string. Beter is bijv. *command==0.
 
Laatst bewerkt:
Kortom : LEKKER!!!

Bedankt voor de info! Het werkt PERFECT!:-D
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan