mituri

[C](server)(zaliczenie) Sprawdzarka cen

Oct 5th, 2015
301
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.76 KB | None | 0 0
  1. #include <sys/socket.h>
  2. #include <arpa/inet.h>
  3. #include <stdio.h>
  4. #include <time.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include <unistd.h>
  8. #include <stdbool.h>
  9. #include <sys/stat.h>
  10.  
  11. /// maksymalny rozmiar tablicy
  12. #define MAX_BUFFER 128
  13. /// maksymalna liczba zgloszen polaczenia z serwerem.
  14. #define MAX_BACKLOG 5
  15. /// dlugosc kodu kreskowego
  16. #define BARCODE_LEN 6
  17.  
  18. /** \brief Struktura przechowywujaca cechy produktu.
  19. *
  20. * Kazdy produkt posiada kod kreskowy, cene oraz nazwe.
  21. */
  22. struct Product{
  23. ///kod kreskowy
  24. int barcode;
  25. ///cena
  26. double price;
  27. ///nazwa
  28. char * name;
  29. }typedef Product;
  30.  
  31. /**
  32. * \brief Sprawdzenie czy przekazany ciag znakow to "administrator".
  33. *
  34. *Funkcja zwracajaca wartosc true, gdy przekazana wiadomosc w tablicy buffer to "adminstrator",
  35. *w przeciwnym wypadku zwraca false. Przekazujemy tablicy znakow tmp ciag "administrator" i porownujemy z przekazana
  36. *tablica buffer. Sprawdzamy czy dla indexu od 0 do 13 czy znaki w obu tablicach sie zgadzaja.
  37. *\param buffer - tablica ktorej sprawdzamy zawartosc.
  38. */
  39. bool isAdmin( char buffer[]){
  40. char tmp[] = "administrator";
  41. int i, sizeOfWord = 13;
  42. bool check = true;
  43. for(i = 0; i < sizeOfWord; i++){
  44. if(buffer[i] != tmp[i]) check = false;
  45. }
  46. return check;
  47. }
  48.  
  49. /** \brief Czyszczenie tablicy.
  50. *
  51. * Funkcja ktora resetuje zawartosc podanej tablicy.
  52. * \param buffer - tablica ktora chcemy zresetowac
  53. * \param size - rozmiar tablicy
  54. */
  55. void clearTab(char buffer[], int size){
  56. int i;
  57. for(i = 0; i < size; i++) buffer[i]= 0;
  58. }
  59.  
  60. /** \brief Pobieranie kodu kreskowego.
  61. *
  62. * Funkcja z podanej tablicy pobiera kod kreskowy. Z przekazanej tablicy znakow pobiera pierwsze 6 cyfr(tyle co nasz BARCODE_LEN) i zwraca jako kod kreskowy typu int.
  63. * \param dataLine - tablica z ktorej pobieramy kod kreskowy
  64. * \param size - rozmiar tablicy
  65. */
  66. int getBarcode(char dataLine[], int size){
  67. char tabTmp[size];
  68. int codeTmp, i;
  69. for(i = 0; i < size; i++){
  70. tabTmp[i] = dataLine[i];
  71. }
  72. codeTmp = atoi(tabTmp);
  73. return codeTmp;
  74. }
  75.  
  76. /** \brief Pobieranie ceny.
  77. *
  78. * Funkcja z podanej tablicy znakow pobiera cene. Z przekazanej tablicy znakow pobiera ciag znakow od pozycji pierwszego znaku pustego ' ' + 1,
  79. * do kolejnego ' ' - 1. Nastepnie zamieniamy je na double poprzez funkcje atof i zwracamy.
  80. * \param dataLine - tablica z ktorej pobieramy kod kreskowy
  81. */
  82. double getPrice(char dataLine[]){
  83. char tabTmp[MAX_BUFFER];
  84. int i, priceEndIndex;
  85. double priceTmp;
  86. int priceIndex = BARCODE_LEN + 1;
  87. for(i = priceIndex; i < (MAX_BUFFER - BARCODE_LEN); i++){
  88. if(dataLine[i] == ' '){
  89. priceEndIndex = i+1;
  90. break;
  91. }
  92. }
  93. for(i = priceIndex; i < priceEndIndex; i++){
  94. tabTmp[i - priceIndex] = dataLine[i];
  95. }
  96. priceTmp = atof(tabTmp);
  97. return priceTmp;
  98. }
  99.  
  100. /** \brief Pobieranie imienia.
  101. *
  102. * Funkcja z podanej tablicy pobiera imie. Z przekazanej tablicy znakow pobiera ciag znakow od pozycji drugiego znaku pustego ' ' + 1 do konca napisu,
  103. * co bedzie stanowic naszą nazwe produktu.
  104. * \param dataLine - tablica z ktorej pobieramy kod kreskowy
  105. */
  106. char* getName(char dataLine[]){
  107. char *tabTmp = malloc(sizeof(char) * MAX_BUFFER);
  108. int nameIndex, i, tmp = 0;
  109. for(i = 0; i < MAX_BUFFER; i++){
  110. if(dataLine[i] == ' ') tmp++;
  111. if(tmp == 2){
  112. nameIndex = i+1;
  113. break;
  114. }
  115. }
  116. for(i = nameIndex; i < (MAX_BUFFER - nameIndex); i++){
  117. tabTmp[i - nameIndex] = dataLine[i];
  118. }
  119. return tabTmp;
  120. }
  121.  
  122. /** \brief Ustalanie parametrow dla produktu.
  123. *
  124. * Funkcja przypisuje produktowi zmienne podane w parametrach funkcji
  125. * \param barCodeTmp - zmienna ktora bedzie stanowic kod kreskowy w naszym produkcie
  126. * \param priceTmp - zmienna ktora bedzie stanowic cene w naszym produkcie
  127. * \param nameTmp - zmienna ktora bedzie stanowic imie naszego produktu
  128. */
  129. Product setProduct(int barCodeTmp, double priceTmp, char *nameTmp){
  130. Product prod;
  131. prod.barcode = barCodeTmp;
  132. prod.price = priceTmp;
  133. prod.name = nameTmp;
  134. return prod;
  135. }
  136.  
  137. /** \brief Wyswietlanie produktu.
  138. *
  139. * Funkcja pokazuje zawartosc skladowych struktury Produkt.
  140. * \param prod - produkt ktory chcemy pokazac.
  141. */
  142. void showProduct(Product prod){
  143. printf("%i %.2f %s", prod.barcode, prod.price, prod.name);
  144. }
  145.  
  146.  
  147. /** \brief Element listy jednokierunkowej
  148. *
  149. * Definicja elementu jednokierunkowej dynamicznej listy produktow.
  150. */
  151. struct Element{
  152. /// Wskaznik na nastepny element listy
  153. struct Element* next;
  154. /// Zawartosc Elementu, czyli Product
  155. Product content;
  156. }typedef Element;
  157.  
  158. /** \brief Lista jednokierunkowa.
  159. *
  160. * Definicja listy jednokierunkowej dynamicznej.
  161. */
  162. struct List{
  163. ///Pierwszy element listy
  164. Element* head;
  165. }typedef List;
  166.  
  167. /** \brief Stworzenie listy.
  168. *
  169. * Funkcja tworzaca liste, przypisujaca pierwszy element jako NULL.
  170. * \param listTmp - lista ktora chcemy stworzyc.
  171. */
  172. void createList(List* listTmp){
  173. listTmp->head = NULL;
  174. }
  175. /** \brief Dodanie elementu do listy.
  176. *
  177. * Funkcja dodaje element do listy. Jesli lista jest pusta to dodaje podany produkt newElem jako pierwszy element listy.
  178. * W innym wypadku wedrujemy na koniec listy i dodajemy produkt na jej koniec
  179. * \param listTmp - lista ktora chcemy stworzyc.
  180. * \param newElem - produkt ktory chcemy dodac do listy.
  181. */
  182. void addElemToList(List* listTmp, Product newElem){
  183. /// elem Elemeny pomocniczy
  184. Element* elem = malloc(sizeof(Element));
  185. elem->content = newElem;
  186. elem->next = NULL;
  187.  
  188. if(listTmp->head == NULL){
  189. listTmp->head = elem;
  190. }else{
  191. Element* elemTmp = listTmp->head;
  192. while(elemTmp->next != NULL){
  193. elemTmp = elemTmp->next;
  194. }
  195. elemTmp->next = elem;
  196. elem->next = NULL;
  197. }
  198. }
  199.  
  200. /** \brief Wyszukiwanie Produktu w liscie.
  201. *
  202. * Funkcja Sprawdza czy lista zawiera produkt o podanym kodzie kreskowym i zwraca false lub true. Jesli znalezlismy
  203. *takowy, to przekazujemy do produku prod adres tego produktu.
  204. *
  205. * \param listTmp - lista ktora chcemy stworzyc.
  206. * \param barcodeTmp - kod kreskowy po ktorym sprawdzamy liste
  207. * \param prod - produkt ktorego zawartosc bedzie stanowila produktu o podanym kodzie kreskowym, jesli takowy produkt istnieje.
  208. */
  209. bool findProduct(List* listTmp,int barcodeTmp, Product* prod){
  210. bool exist = false;
  211. Element* elemTmp = listTmp->head;
  212. while(elemTmp->next != NULL){
  213. if(elemTmp->content.barcode == barcodeTmp){
  214. exist = true;
  215. *prod = elemTmp->content;
  216. elemTmp->content;
  217. }
  218. elemTmp = elemTmp->next;
  219. }
  220. if(elemTmp->content.barcode == barcodeTmp){
  221. exist = true;
  222. *prod = elemTmp->content;
  223. elemTmp->content;
  224. }
  225. elemTmp = elemTmp->next;
  226.  
  227. return exist;
  228. }
  229.  
  230. /** \brief Wyswietlanie listy.
  231. *
  232. * Funkcja przechodzi przez cala liste i wyswietla kazdy element listy.
  233. * \param listTmp - lista ktora chcemy wyswietlic.
  234. */
  235. void showList(List listTmp){
  236. Element* elemTmp = listTmp.head;
  237. Product prodTmp;
  238. while(elemTmp->next!= NULL){
  239. prodTmp = elemTmp->content;
  240. showProduct(prodTmp);
  241. elemTmp = elemTmp->next;
  242. }
  243. if(elemTmp->next == NULL){
  244. prodTmp = elemTmp->content;
  245. showProduct(prodTmp);
  246. }
  247. }
  248.  
  249. /** \brief Przekazanie wartosci listy do dynamicznej tablicy.
  250. *
  251. * Funkcja leci po kazdym elemencie listy i dodaje do tablicy znakow zawartosc prdoduktow zamienionych na znaki.
  252. *
  253. * \param listTmp - lista ktorej elementy chcemy przekazac.
  254. * \param charFinal - tablica napisow ktora bedzie zawierac zawartosc wszystkich skladowych produktow listy.
  255. */
  256. void sendList(List listTmp, char **charFinal){
  257. clearTab(*charFinal, MAX_BUFFER );
  258. Element* elemTmp = listTmp.head;
  259. Product prodTmp;
  260. char *charTmp = malloc(sizeof(char) * MAX_BUFFER);
  261. while(elemTmp){
  262. prodTmp = elemTmp->content;
  263. asprintf(&charTmp, "%i %.2f %s", prodTmp.barcode, prodTmp.price, prodTmp.name);
  264. strcat(*charFinal, charTmp);
  265. elemTmp = elemTmp->next;
  266.  
  267. }
  268. }
  269.  
  270. /** \brief Przekazanie zawartosci produktow z listy do pliku tekstowego.
  271. *
  272. * Funkcja sprawdza czy istnieje nasza baza danych, nastepnie wykorzystuje fukncje sendList aby przekazac tablicy zawartosc produktow z listy.
  273. * Jako kolejny krok, za pomoca fprintf() zapisujemy do pliku nasza tablice.
  274. * \param listTmp - lista ktorej elementy chcemy przekazac.
  275. */
  276. void addToFile(List listTmp){
  277.  
  278. FILE *file;
  279. file = fopen("bazaDanych.txt", "w");
  280. if(file == NULL){
  281. fprintf(stderr, "Nie udalo sie znalesc pliku bazaDanych!\n");
  282. exit(1);
  283. }
  284.  
  285. char *tmpTab = malloc(MAX_BUFFER* sizeof(char));
  286. sendList(listTmp, &tmpTab);
  287. printf("%s", tmpTab);
  288. fprintf(file, "%s", tmpTab);
  289. fclose(file);
  290. }
  291.  
  292. /** \brief Usuniecie produktu z listy
  293. * Funkcja usuwa z listy produkt o podanym kodzie kreskowym. Sprawdzamy kazdy kod kreskowy produkow w liscie, dopoki nie dojedziemy
  294. * do produktu ktorej wartosc next wynosi NULL. Ostatecznie zapisujemy nasza liste do naszej bazy danych.
  295. *
  296. * \para listTmp - lista ktorej elementy chcemy zmodyfikowac.
  297. * \para barcodeTmp - kod kreskowy produktu, ktory chcemy usunac z listy.
  298. */
  299. void removeProduct(List* listTmp, int barcodeTmp){
  300.  
  301. Element* elemFirst = listTmp->head;
  302. Element*elemNext = malloc(sizeof(Element));
  303.  
  304. if(elemFirst->content.barcode == barcodeTmp){
  305. listTmp->head = elemFirst->next;
  306.  
  307. }else{
  308. while(elemFirst->next != NULL){
  309. elemNext = elemFirst->next;
  310.  
  311. if(elemNext->content.barcode == barcodeTmp){
  312. elemFirst->next = elemNext->next;
  313. }
  314. if(elemFirst->next != NULL) elemFirst = elemFirst->next;
  315. }
  316. if(elemNext->content.barcode == barcodeTmp){
  317. elemFirst->next = NULL;
  318. }
  319. }
  320. addToFile(*listTmp);
  321. }
  322.  
  323. /** \brief Zapelnienie listy produktami zawartymi w pliku tekstowym.
  324. *
  325. * Funkcja na poczatku sprawdza czy nasza baza danych istnieje. Tworzymy liste, nastepnie
  326. * przakazujemy do niej produkty ktorych dane sa zawarte w naszej bazie danych.
  327. *
  328. * \para fileName - nazwa pliku z ktorego chcemy pobierac produkty.
  329. * \para list - lista ktora chcemy zapelnic.
  330. */
  331. void getProdFromFileToList( char* fileName, List * list){
  332. FILE *file;
  333. file = fopen(fileName, "r");
  334. if(file == NULL){
  335. fprintf(stderr, "Nie udalo sie znalesc pliku bazaDanych!\n");
  336. exit(1);
  337. }
  338.  
  339. char dataLine[MAX_BUFFER];
  340. int codeTmp; double priceTmp; char *nameTmp;
  341.  
  342. createList(list);
  343.  
  344. while (1) {
  345. if (fgets(dataLine,MAX_BUFFER, file) == NULL) break;
  346.  
  347. codeTmp = getBarcode(dataLine, BARCODE_LEN);
  348. priceTmp = getPrice(dataLine);
  349. nameTmp = getName(dataLine);
  350.  
  351. Product prod = setProduct(codeTmp, priceTmp, nameTmp);
  352. addElemToList(list, prod);
  353. }
  354. fclose(file);
  355. }
  356.  
  357. /** \brief Stworzenie gniazda.
  358. *
  359. * Funkcja zwraca deskryptor pliku jako wynik funkcji socket(). Jesli operacja sie nie udala zwracamy wiadomosc i zatrzymujemy program.
  360. */
  361. int createSocket(){
  362. int serverFd;
  363. if ( (serverFd = socket(PF_INET, SOCK_STREAM, 0)) < 0){
  364. perror("Socket() - nie udalo sie");
  365. exit(1);
  366. }
  367. return serverFd;
  368.  
  369. }
  370. ///////////////////////////////////////////////////////////////////////////////////
  371.  
  372. /**
  373. * \brief Sprawdzarka cen - server.
  374. *
  375. * Do dzialania naszego programu uzywamy protokolou Tcp. W argumencie wywolania podany nam zostaje port na ktorym
  376. * bedzie dzialal nasz program. Tworzymy gniazdo za pomoca funkcji socket(), nastepnie wykorzystujemy funcke bind()
  377. * oraz listen() i oczekujemy polaczenia. Wykorzystujemy accept() do nawiazania polączenia z klientem. Pobieramy z
  378. * pliku tekstowego "bazaDanych.txt" produkty do listy jednokierunkowej. Od klienta dostajemy wiadomosc.
  379. * Jesli to szesciocyfrowy kod kreskowy, to sprawdzamy czy posiadamy w naszej liscie produkt o danym kodzie.
  380. * Jesli tak, to odsylamy do klienta tablice znakow, ktora zawiwera wartosci skladowych tego produktu, w
  381. * przeciwnym wypadku, informacje o braku takowego produktu. Jesli klient przekazal nam wiadomosc "administrator"
  382. * to wysylamy do klienta wiadomosc "Panel administratora" razem z opcjami: 1.pokaz prodkuty, 2.dodaj produkt
  383. * 3. usun produkt, 4. wyjdz. Nastepnie w petli do-while oczekujemy na wiadomosc od klienta, jaka opcje wybral
  384. * i jesli wybral opcje 1, 2 lub 3 to realizujemy polecenie.
  385. *
  386. * Do wykonania 1 polecenia wykorzystujemy nasza funkcje sendList() i wysylamy do klienta nasza tablice zawierajaca
  387. * wszystkie dane produktow z listy.
  388. *
  389. * Do wykonania 2 polecania serwer wysyla do klienta wiadomosc "Podaj szesciocyfrowy kod kreskowy, cene i nazwe produktu" i oczekujemy
  390. * na odpowiedz. Ze zwroconegej tablicy znakow pobieramy do produktu prodTmp wartosci jej skladowych za pomoca funkcji getBarcode(), getPrice(), getName().
  391. * Nastepnie wykorzystujemy nasza funkcje addElemToList() do przekazania prodTmp do listy.
  392. *
  393. * Do wykonania 3 polecenia prosimy client o podanie szesciocyfrowego kodu kreskowego. Nastepnie wykorzystujemy funkcje removeProduct()
  394. * do usuniecia produktu o wskazanym kodzie.
  395. *
  396. * Zamykamy nasz polaczenie.
  397. */
  398.  
  399.  
  400.  
  401.  
  402. int main(int argc, int *argv[]){
  403.  
  404. int serverFd, connectionFd;
  405. struct sockaddr_in servaddr;
  406. struct sockaddr_storage servStorage;
  407. socklen_t addrSize;
  408. char buffer[MAX_BUFFER +1];
  409. char result[MAX_BUFFER +1];
  410.  
  411.  
  412. if (argc != 2) {
  413. fprintf(stderr, "Usage: %s <Server Port>\n", argv[0]);
  414. exit(1);
  415. }
  416.  
  417. int port = atoi(argv[1]);
  418.  
  419. serverFd = createSocket();
  420.  
  421. memset(&servaddr, 0 ,sizeof(servaddr));
  422. servaddr.sin_family = AF_INET;
  423. servaddr.sin_port = htons(port);
  424. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  425.  
  426. if ( (bind(serverFd, (struct sockaddr *)&servaddr, sizeof(servaddr)) ) < 0){
  427. perror("bind() - nie udalo sie");
  428. exit(1);
  429. }
  430.  
  431. if(listen(serverFd, MAX_BACKLOG) < 0){
  432. perror("listen() - nie udalo sie");
  433. exit(1);
  434. }
  435. else{
  436. system("clear");
  437. printf("Serwer aktywny. Oczekuje polaczenia...\n");
  438. }
  439.  
  440. addrSize = sizeof(servStorage);
  441. if( (connectionFd = accept(serverFd, (struct sockaddr*)&servStorage, &addrSize) ) < 0 ){
  442. perror("accept() - nie udalo sie");
  443. exit(1);
  444. }
  445.  
  446. if( (recv(connectionFd, buffer, MAX_BUFFER, 0)) < 0){
  447. perror("recv() - nie udalo sie \n");
  448. exit(1);
  449. }
  450. printf("Otrzymano kod: %s \n",buffer); // # 1 ODEBRANO WIADMOSC
  451.  
  452. List *list = malloc(sizeof(List));
  453. getProdFromFileToList("bazaDanych.txt", list);
  454.  
  455.  
  456.  
  457. int codeTmp;
  458.  
  459. bool status;
  460. int optionInt;
  461.  
  462. if(isAdmin(buffer)){ // 3.1 sprawdzamy wiadomosc
  463.  
  464. clearTab(result, MAX_BUFFER);
  465.  
  466. strcat(result, "Panel administratora. Wybierz operacje:\n1.pokaz produkty\n2.dodaj produkt\n3.usun produkt\n4.wyjdz\n");
  467. char* option = malloc(MAX_BUFFER * sizeof(char));
  468.  
  469. if( (send(connectionFd, result, MAX_BUFFER, 0)) < 0){
  470. perror("send() - nie udalo sie \n");
  471. exit(1);
  472. }
  473.  
  474. clearTab(option, MAX_BUFFER);
  475. do{
  476. if( (recv(connectionFd, option, MAX_BUFFER, 0)) < 0){
  477. perror("recv() - nie udalo sie \n");
  478. exit(1);
  479. }
  480. optionInt = atoi(option);
  481. char *tmpTab = malloc(MAX_BUFFER* sizeof(char));
  482.  
  483. switch(optionInt){
  484. case 1 :{
  485.  
  486. sendList(*list, &tmpTab);
  487. if( (send(connectionFd, tmpTab, MAX_BUFFER, 0)) < 0){
  488. perror("send() - nie udalo sie \n");
  489. exit(1);
  490. };
  491. break;
  492. }
  493. case 2: {
  494. clearTab(tmpTab, MAX_BUFFER);
  495. tmpTab = "Podaj szesciocyfrowy kod kreskowy, cene i nazwe produktu\n";
  496. if( (send(connectionFd, tmpTab, MAX_BUFFER, 0)) < 0){
  497. perror("send() - nie udalo sie \n");
  498. exit(1);
  499. }
  500.  
  501. clearTab(result, MAX_BUFFER);
  502. if( (recv(connectionFd, result, MAX_BUFFER, 0)) < 0){
  503. perror("recv() - nie udalo sie \n");
  504. exit(1);
  505. }
  506.  
  507. Product prodTmp;
  508. prodTmp.barcode = getBarcode(result, BARCODE_LEN);
  509. prodTmp.price = getPrice(result);
  510. prodTmp.name = getName(result);
  511.  
  512. addElemToList(list, prodTmp);
  513.  
  514. clearTab(&result, MAX_BUFFER);
  515. addToFile(*list);
  516. };break;
  517.  
  518. case 3:{
  519. clearTab(tmpTab, MAX_BUFFER);
  520. tmpTab = "Podaj szesciocyfrowy kod kreskowy produktu ktory chcesz usunac: \n";
  521. if( (send(connectionFd, tmpTab, MAX_BUFFER, 0)) < 0){
  522. perror("send() - nie udalo sie \n");
  523. exit(1);
  524. }
  525. clearTab(result, MAX_BUFFER);
  526. if( (recv(connectionFd, result, MAX_BUFFER, 0)) < 0){
  527. perror("recv() - nie udalo sie \n");
  528. exit(1);
  529. }
  530. //printf("%s", result);
  531. codeTmp = atoi(result);
  532.  
  533. removeProduct(list, codeTmp);
  534. };break;
  535.  
  536. default: ;break;
  537. }
  538. }while(optionInt == 1 || optionInt == 2 || optionInt == 3);
  539.  
  540. }else{ // JESLI NIE ADMIN !!!!!!!!!!!!!!!!!!!!!!!!!!1
  541. codeTmp = atoi(buffer);
  542. Product prodTmp;
  543. if(findProduct(list, codeTmp, &prodTmp )){ //jesli jest taki barKod
  544. snprintf(result, sizeof(result), "%i %.2f %s", prodTmp.barcode, prodTmp.price, prodTmp.name);
  545. }else{
  546. clearTab(result, MAX_BUFFER);
  547. strcat(result, "produkt o wskazanym kodzie kreskowym nie istnieje!");
  548. }
  549.  
  550. if( (send(connectionFd, result, MAX_BUFFER, 0)) < 0){
  551. perror("send() - nie udalo sie \n");
  552. exit(1);
  553. }
  554. }
  555.  
  556. if( (close(serverFd)) < 0){
  557. perror("close() - nie udalo sie \n");
  558. exit(1);
  559. }
  560.  
  561. return(0);
  562. }
Advertisement
Add Comment
Please, Sign In to add comment