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 :
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!
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: