// Primer labi ¹ 3 - klient-servernoe prilozenie Windows // server #include <conio.h> #include <iostream> #include <windows.h> #define FILENAME "userdata" #define ADD_USER '1' #define EDIT_USER '2' #define DELETE_USER '3' #define CHANGE_PWD '4' #define VIEW_USERS '5' #define ADD_RATING '6' #define PURGE '7' #define FINISH '8' using namespace std; struct User{ int exist; // 0 - if deleted, 1 - otherwise char login[11]; char passwd[21]; int rating; User(){ // constructor exist=0; login[0]=0; passwd[0]=0; rating=0; } }; // main functions void Add_User(); void Print_Users(); void Edit_User(); int Find_User(); void Delete_User(); void Change_Pwd(); void Add_Rating(); void Purge(); // service functions void load(); void save(); void openPipe(); void initStrings(); void myExit(); int quant; //number of records struct User *arr; //array for data HANDLE hPipe; // Pipe handle wchar_t *pipename= L"\\\\.\\pipe\\oslab3"; int main(int argc, char* argv[]){ int code=0; //kod operacii, proslannoi klientom load(); openPipe(); // Main cycle of program // Chitaem kod commandi, poka ne vstretitsia 8 while(code!=FINISH){ int retCode; DWORD bytesRead; retCode=ReadFile(hPipe,(void*)&code,sizeof(int),&bytesRead,NULL); if(!retCode){ printf("Couldn't read action code"); myExit(); } switch(code){ case ADD_USER:Add_User();break; case VIEW_USERS:Print_Users();break; case EDIT_USER:Edit_User();break; case DELETE_USER:Delete_User();break; case CHANGE_PWD:Change_Pwd();break; case ADD_RATING:Add_Rating();break; case PURGE:Purge();break; default: break; } } save(); myExit(); return 0; } void myExit(){ CloseHandle(hPipe); // Close pipe handle printf("Server finish its work. Press any key to exit ..."); _getch(); exit(0); } void openPipe(){ // Zdem osvobozdenia kanala 20 sekund if (!WaitNamedPipe(pipename, 20000)){ printf("No free pipe."); myExit(); } // open pipe hPipe = CreateFile(pipename,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); if(hPipe == INVALID_HANDLE_VALUE) { printf("Could not open pipe"); myExit(); } // Ustanovit' rezim chtenia soobshenii DWORD dwMode = PIPE_READMODE_MESSAGE; int fSuccess = SetNamedPipeHandleState(hPipe,&dwMode,NULL,NULL); if (!fSuccess){ printf("SetNamedPipeHandleState failed"); myExit(); } } void Add_User(){ //Videlenie massivqa dlinoq na 1 bolshe predidushego struct User* tmp_arr = new User[quant+1]; //Perepisivaem starii massiv memcpy(tmp_arr,arr,sizeof(struct User)*quant); delete[] arr; arr = tmp_arr; User tmpUser; int retCode; DWORD bytesRead; // Polutchit' opisanie nivigi polzovatelia v User retCode=ReadFile(hPipe,(void*)&tmpUser,sizeof(User),&bytesRead,NULL); if(!retCode || bytesRead!=sizeof(User)){ printf("Can't read new user from pipe"); myExit(); } arr[quant]=tmpUser; quant++; } void Print_Users(){ int i, st=0, // number of real records retCode; DWORD bytesWritten; for(i=0;i<quant;i++) if(arr[i].exist)// if record isn't deleted st++; // Send to client number of records retCode=WriteFile(hPipe,(void*)&st,sizeof(int),&bytesWritten,NULL); if(!retCode || bytesWritten!=sizeof(int)){ printf("Can't write number of student to pipe for output"); myExit(); } // Send one user per one cycle iteration for(i=0;i<quant;i++) if(arr[i].exist) { retCode=WriteFile(hPipe,(void*)&arr[i],sizeof(User),&bytesWritten,NULL); if(!retCode || bytesWritten!=sizeof(User)){ printf("Can't write student to pipe"); myExit(); } } } void Edit_User(){ int i, // Number of edited user retCode; DWORD bytesRead,bytesWritten; User tmpUser; i=Find_User(); if(i==-1)return; // Search fails // Send old user information retCode=WriteFile(hPipe,(void*)&arr[i],sizeof(User),&bytesWritten,NULL); if(!retCode || bytesWritten!=sizeof(User)){ printf("Can't write student to pipe for edition"); myExit(); } // Read new user information retCode=ReadFile(hPipe,(void*)&tmpUser,sizeof(User),&bytesRead,NULL); if(!retCode || bytesRead!=sizeof(User)){ printf("Can't read edited user from pipe"); myExit(); } strcpy_s(arr[i].login,11,tmpUser.login); strcpy_s(arr[i].passwd,21,tmpUser.passwd); arr[i].rating=tmpUser.rating;/ } int Find_User(){ int i, // i - ïîðÿäêîâûé íîìåð èñêîìîé çàï; fl1,// fl1 - Flag - priznak uspeshnoi zapisi res,// res - vozvrashaemoe znachenie - libo nomer zapisi libo kod neudachi poiska retCode; DWORD bytesRead,bytesWritten; User tmpUser; res=-1; while(res==-1) { // read login retCode=ReadFile(hPipe,(void*)&tmpUser,sizeof(User),&bytesRead,NULL); if(!retCode || bytesRead!=sizeof(User)){ printf("Can't read user login from pipe"); myExit(); } if(tmpUser.exist==-1)// if client otpravil otkaz ot zapisi return -1; fl1=0;i=0; while(!fl1 && i<quant) { if(arr[i].exist) if(strcmp(tmpUser.login,arr[i].login)==0) { fl1=1; res=i;/ } i++; } if(res==-1) tmpUser.exist=-1; // Ustanovit privnak togo chto ne nashli fail else tmpUser.exist=777;// Ustanovit privnak togo chto nashli fail // Send results to client and wait response retCode=WriteFile(hPipe,(void*)&tmpUser,sizeof(User),&bytesWritten,NULL); if(!retCode || bytesWritten!=sizeof(User)){ printf("Can't write search results to pipe"); myExit(); } } return res; } void Delete_User(){ int i, retCode; DWORD bytesWritten; User tmpUser; i=Find_User(); if(i==-1)return; arr[i].exist=0; tmpUser.exist=777; retCode=WriteFile(hPipe,(void*)&tmpUser,sizeof(User),&bytesWritten,NULL); if(!retCode || bytesWritten!=sizeof(User)){ printf("Can't write delete result to pipe"); myExit(); } } void Change_Pwd(){ int i, retCode; DWORD bytesRead,bytesWritten; User tmpUser; i=Find_User(); if(i==-1)return; retCode=WriteFile(hPipe,(void*)&arr[i],sizeof(User),&bytesWritten,NULL); if(!retCode || bytesWritten!=sizeof(User)){ printf("Can't write student to pipe for password changing"); myExit(); } retCode=ReadFile(hPipe,(void*)&tmpUser,sizeof(User),&bytesRead,NULL); if(!retCode || bytesRead!=sizeof(User)){ printf("Can't read edited password from pipe"); myExit(); } strcpy_s(arr[i].passwd,21,tmpUser.passwd); } void Add_Rating(){ int i, retCode; DWORD bytesRead,bytesWritten; User tmpUser; i=Find_User(); if(i==-1)return; retCode=WriteFile(hPipe,(void*)&arr[i],sizeof(User),&bytesWritten,NULL); if(!retCode || bytesWritten!=sizeof(User)){ printf("Can't write student to pipe for password edition"); myExit(); } retCode=ReadFile(hPipe,(void*)&tmpUser,sizeof(User),&bytesRead,NULL); if(!retCode || bytesRead!=sizeof(User)){ printf("SERVER: Can't read edited password from pipe"); myExit(); } arr[i].rating+=tmpUser.rating; } void Purge(){ int i,j; printf("Please wait while purging database\n"); int rec_num=0; for(int i=0;i<quant;i++) if(arr[i].exist!=0) rec_num++; struct User* tmp_arr = new User[rec_num]; j=0; for(i=0;i<quant;i++) if(arr[i].exist){ tmp_arr[j]=arr[i]; j++; } delete[] arr; arr = tmp_arr; quant=rec_num; printf("Purging complete\n"); } void load(){ int count=0; HANDLE file; DWORD readBytes,bytesWritten; int retCode; struct User tmp; file = CreateFile(TEXT(FILENAME), GENERIC_WRITE|GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); if(file == INVALID_HANDLE_VALUE){ // Âûçîâ çàâåðøèëñÿ íåóäà÷åé, ò.å. ôàéëà íå ñóùåñòâóåò file = CreateFile(TEXT(FILENAME), GENERIC_WRITE|GENERIC_READ, 0, 0, CREATE_NEW, 0, 0); count=0; WriteFile(file,(void*)&count,sizeof(int),&bytesWritten,0); arr = NULL; } else { retCode=ReadFile(file,(void*)&count, sizeof(int), &readBytes, 0); if(!retCode || readBytes!=sizeof(int)){ printf("Can't read the file.\n"); count=0; arr=NULL; return; } arr = (struct User*)new struct User[count]; int curNumber=0; while(curNumber<count && ReadFile(file,(void*)&arr[curNumber], sizeof(struct User), &readBytes, 0)){ // ïðî÷èòàòü îäíó ñòðóêòóðó if(readBytes!=sizeof(struct User)) break; curNumber++; } } CloseHandle(file); quant = count; } void save(){ HANDLE file; DWORD bytesWritten; int retCode; file = CreateFile(TEXT(FILENAME),GENERIC_WRITE, 0, NULL,CREATE_ALWAYS, 0, NULL); if(file == INVALID_HANDLE_VALUE){ DWORD le = GetLastError(); printf("Can't create the file %s.\n",FILENAME); return; } retCode=WriteFile(file,(void*)&quant, sizeof(int), &bytesWritten, 0); if(!retCode || bytesWritten!=sizeof(int)){ printf("Can't write count to the file.\n"); return; } int curNumber=0; while(WriteFile(file,(void*)&arr[curNumber], sizeof(struct User), &bytesWritten, 0) && curNumber<quant){ if(bytesWritten!=sizeof(struct User)){ printf("Can't write structure to the file.\n"); return; } curNumber++; } CloseHandle(file); }