Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <stdio.h>
- #include <time.h>
- #include <string.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <stdbool.h>
- #include <sys/stat.h>
- /// maksymalny rozmiar tablicy
- #define MAX_BUFFER 128
- /// maksymalna liczba zgloszen polaczenia z serwerem.
- #define MAX_BACKLOG 5
- /// dlugosc kodu kreskowego
- #define BARCODE_LEN 6
- /** \brief Struktura przechowywujaca cechy produktu.
- *
- * Kazdy produkt posiada kod kreskowy, cene oraz nazwe.
- */
- struct Product{
- ///kod kreskowy
- int barcode;
- ///cena
- double price;
- ///nazwa
- char * name;
- }typedef Product;
- /**
- * \brief Sprawdzenie czy przekazany ciag znakow to "administrator".
- *
- *Funkcja zwracajaca wartosc true, gdy przekazana wiadomosc w tablicy buffer to "adminstrator",
- *w przeciwnym wypadku zwraca false. Przekazujemy tablicy znakow tmp ciag "administrator" i porownujemy z przekazana
- *tablica buffer. Sprawdzamy czy dla indexu od 0 do 13 czy znaki w obu tablicach sie zgadzaja.
- *\param buffer - tablica ktorej sprawdzamy zawartosc.
- */
- bool isAdmin( char buffer[]){
- char tmp[] = "administrator";
- int i, sizeOfWord = 13;
- bool check = true;
- for(i = 0; i < sizeOfWord; i++){
- if(buffer[i] != tmp[i]) check = false;
- }
- return check;
- }
- /** \brief Czyszczenie tablicy.
- *
- * Funkcja ktora resetuje zawartosc podanej tablicy.
- * \param buffer - tablica ktora chcemy zresetowac
- * \param size - rozmiar tablicy
- */
- void clearTab(char buffer[], int size){
- int i;
- for(i = 0; i < size; i++) buffer[i]= 0;
- }
- /** \brief Pobieranie kodu kreskowego.
- *
- * 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.
- * \param dataLine - tablica z ktorej pobieramy kod kreskowy
- * \param size - rozmiar tablicy
- */
- int getBarcode(char dataLine[], int size){
- char tabTmp[size];
- int codeTmp, i;
- for(i = 0; i < size; i++){
- tabTmp[i] = dataLine[i];
- }
- codeTmp = atoi(tabTmp);
- return codeTmp;
- }
- /** \brief Pobieranie ceny.
- *
- * Funkcja z podanej tablicy znakow pobiera cene. Z przekazanej tablicy znakow pobiera ciag znakow od pozycji pierwszego znaku pustego ' ' + 1,
- * do kolejnego ' ' - 1. Nastepnie zamieniamy je na double poprzez funkcje atof i zwracamy.
- * \param dataLine - tablica z ktorej pobieramy kod kreskowy
- */
- double getPrice(char dataLine[]){
- char tabTmp[MAX_BUFFER];
- int i, priceEndIndex;
- double priceTmp;
- int priceIndex = BARCODE_LEN + 1;
- for(i = priceIndex; i < (MAX_BUFFER - BARCODE_LEN); i++){
- if(dataLine[i] == ' '){
- priceEndIndex = i+1;
- break;
- }
- }
- for(i = priceIndex; i < priceEndIndex; i++){
- tabTmp[i - priceIndex] = dataLine[i];
- }
- priceTmp = atof(tabTmp);
- return priceTmp;
- }
- /** \brief Pobieranie imienia.
- *
- * Funkcja z podanej tablicy pobiera imie. Z przekazanej tablicy znakow pobiera ciag znakow od pozycji drugiego znaku pustego ' ' + 1 do konca napisu,
- * co bedzie stanowic naszą nazwe produktu.
- * \param dataLine - tablica z ktorej pobieramy kod kreskowy
- */
- char* getName(char dataLine[]){
- char *tabTmp = malloc(sizeof(char) * MAX_BUFFER);
- int nameIndex, i, tmp = 0;
- for(i = 0; i < MAX_BUFFER; i++){
- if(dataLine[i] == ' ') tmp++;
- if(tmp == 2){
- nameIndex = i+1;
- break;
- }
- }
- for(i = nameIndex; i < (MAX_BUFFER - nameIndex); i++){
- tabTmp[i - nameIndex] = dataLine[i];
- }
- return tabTmp;
- }
- /** \brief Ustalanie parametrow dla produktu.
- *
- * Funkcja przypisuje produktowi zmienne podane w parametrach funkcji
- * \param barCodeTmp - zmienna ktora bedzie stanowic kod kreskowy w naszym produkcie
- * \param priceTmp - zmienna ktora bedzie stanowic cene w naszym produkcie
- * \param nameTmp - zmienna ktora bedzie stanowic imie naszego produktu
- */
- Product setProduct(int barCodeTmp, double priceTmp, char *nameTmp){
- Product prod;
- prod.barcode = barCodeTmp;
- prod.price = priceTmp;
- prod.name = nameTmp;
- return prod;
- }
- /** \brief Wyswietlanie produktu.
- *
- * Funkcja pokazuje zawartosc skladowych struktury Produkt.
- * \param prod - produkt ktory chcemy pokazac.
- */
- void showProduct(Product prod){
- printf("%i %.2f %s", prod.barcode, prod.price, prod.name);
- }
- /** \brief Element listy jednokierunkowej
- *
- * Definicja elementu jednokierunkowej dynamicznej listy produktow.
- */
- struct Element{
- /// Wskaznik na nastepny element listy
- struct Element* next;
- /// Zawartosc Elementu, czyli Product
- Product content;
- }typedef Element;
- /** \brief Lista jednokierunkowa.
- *
- * Definicja listy jednokierunkowej dynamicznej.
- */
- struct List{
- ///Pierwszy element listy
- Element* head;
- }typedef List;
- /** \brief Stworzenie listy.
- *
- * Funkcja tworzaca liste, przypisujaca pierwszy element jako NULL.
- * \param listTmp - lista ktora chcemy stworzyc.
- */
- void createList(List* listTmp){
- listTmp->head = NULL;
- }
- /** \brief Dodanie elementu do listy.
- *
- * Funkcja dodaje element do listy. Jesli lista jest pusta to dodaje podany produkt newElem jako pierwszy element listy.
- * W innym wypadku wedrujemy na koniec listy i dodajemy produkt na jej koniec
- * \param listTmp - lista ktora chcemy stworzyc.
- * \param newElem - produkt ktory chcemy dodac do listy.
- */
- void addElemToList(List* listTmp, Product newElem){
- /// elem Elemeny pomocniczy
- Element* elem = malloc(sizeof(Element));
- elem->content = newElem;
- elem->next = NULL;
- if(listTmp->head == NULL){
- listTmp->head = elem;
- }else{
- Element* elemTmp = listTmp->head;
- while(elemTmp->next != NULL){
- elemTmp = elemTmp->next;
- }
- elemTmp->next = elem;
- elem->next = NULL;
- }
- }
- /** \brief Wyszukiwanie Produktu w liscie.
- *
- * Funkcja Sprawdza czy lista zawiera produkt o podanym kodzie kreskowym i zwraca false lub true. Jesli znalezlismy
- *takowy, to przekazujemy do produku prod adres tego produktu.
- *
- * \param listTmp - lista ktora chcemy stworzyc.
- * \param barcodeTmp - kod kreskowy po ktorym sprawdzamy liste
- * \param prod - produkt ktorego zawartosc bedzie stanowila produktu o podanym kodzie kreskowym, jesli takowy produkt istnieje.
- */
- bool findProduct(List* listTmp,int barcodeTmp, Product* prod){
- bool exist = false;
- Element* elemTmp = listTmp->head;
- while(elemTmp->next != NULL){
- if(elemTmp->content.barcode == barcodeTmp){
- exist = true;
- *prod = elemTmp->content;
- elemTmp->content;
- }
- elemTmp = elemTmp->next;
- }
- if(elemTmp->content.barcode == barcodeTmp){
- exist = true;
- *prod = elemTmp->content;
- elemTmp->content;
- }
- elemTmp = elemTmp->next;
- return exist;
- }
- /** \brief Wyswietlanie listy.
- *
- * Funkcja przechodzi przez cala liste i wyswietla kazdy element listy.
- * \param listTmp - lista ktora chcemy wyswietlic.
- */
- void showList(List listTmp){
- Element* elemTmp = listTmp.head;
- Product prodTmp;
- while(elemTmp->next!= NULL){
- prodTmp = elemTmp->content;
- showProduct(prodTmp);
- elemTmp = elemTmp->next;
- }
- if(elemTmp->next == NULL){
- prodTmp = elemTmp->content;
- showProduct(prodTmp);
- }
- }
- /** \brief Przekazanie wartosci listy do dynamicznej tablicy.
- *
- * Funkcja leci po kazdym elemencie listy i dodaje do tablicy znakow zawartosc prdoduktow zamienionych na znaki.
- *
- * \param listTmp - lista ktorej elementy chcemy przekazac.
- * \param charFinal - tablica napisow ktora bedzie zawierac zawartosc wszystkich skladowych produktow listy.
- */
- void sendList(List listTmp, char **charFinal){
- clearTab(*charFinal, MAX_BUFFER );
- Element* elemTmp = listTmp.head;
- Product prodTmp;
- char *charTmp = malloc(sizeof(char) * MAX_BUFFER);
- while(elemTmp){
- prodTmp = elemTmp->content;
- asprintf(&charTmp, "%i %.2f %s", prodTmp.barcode, prodTmp.price, prodTmp.name);
- strcat(*charFinal, charTmp);
- elemTmp = elemTmp->next;
- }
- }
- /** \brief Przekazanie zawartosci produktow z listy do pliku tekstowego.
- *
- * Funkcja sprawdza czy istnieje nasza baza danych, nastepnie wykorzystuje fukncje sendList aby przekazac tablicy zawartosc produktow z listy.
- * Jako kolejny krok, za pomoca fprintf() zapisujemy do pliku nasza tablice.
- * \param listTmp - lista ktorej elementy chcemy przekazac.
- */
- void addToFile(List listTmp){
- FILE *file;
- file = fopen("bazaDanych.txt", "w");
- if(file == NULL){
- fprintf(stderr, "Nie udalo sie znalesc pliku bazaDanych!\n");
- exit(1);
- }
- char *tmpTab = malloc(MAX_BUFFER* sizeof(char));
- sendList(listTmp, &tmpTab);
- printf("%s", tmpTab);
- fprintf(file, "%s", tmpTab);
- fclose(file);
- }
- /** \brief Usuniecie produktu z listy
- * Funkcja usuwa z listy produkt o podanym kodzie kreskowym. Sprawdzamy kazdy kod kreskowy produkow w liscie, dopoki nie dojedziemy
- * do produktu ktorej wartosc next wynosi NULL. Ostatecznie zapisujemy nasza liste do naszej bazy danych.
- *
- * \para listTmp - lista ktorej elementy chcemy zmodyfikowac.
- * \para barcodeTmp - kod kreskowy produktu, ktory chcemy usunac z listy.
- */
- void removeProduct(List* listTmp, int barcodeTmp){
- Element* elemFirst = listTmp->head;
- Element*elemNext = malloc(sizeof(Element));
- if(elemFirst->content.barcode == barcodeTmp){
- listTmp->head = elemFirst->next;
- }else{
- while(elemFirst->next != NULL){
- elemNext = elemFirst->next;
- if(elemNext->content.barcode == barcodeTmp){
- elemFirst->next = elemNext->next;
- }
- if(elemFirst->next != NULL) elemFirst = elemFirst->next;
- }
- if(elemNext->content.barcode == barcodeTmp){
- elemFirst->next = NULL;
- }
- }
- addToFile(*listTmp);
- }
- /** \brief Zapelnienie listy produktami zawartymi w pliku tekstowym.
- *
- * Funkcja na poczatku sprawdza czy nasza baza danych istnieje. Tworzymy liste, nastepnie
- * przakazujemy do niej produkty ktorych dane sa zawarte w naszej bazie danych.
- *
- * \para fileName - nazwa pliku z ktorego chcemy pobierac produkty.
- * \para list - lista ktora chcemy zapelnic.
- */
- void getProdFromFileToList( char* fileName, List * list){
- FILE *file;
- file = fopen(fileName, "r");
- if(file == NULL){
- fprintf(stderr, "Nie udalo sie znalesc pliku bazaDanych!\n");
- exit(1);
- }
- char dataLine[MAX_BUFFER];
- int codeTmp; double priceTmp; char *nameTmp;
- createList(list);
- while (1) {
- if (fgets(dataLine,MAX_BUFFER, file) == NULL) break;
- codeTmp = getBarcode(dataLine, BARCODE_LEN);
- priceTmp = getPrice(dataLine);
- nameTmp = getName(dataLine);
- Product prod = setProduct(codeTmp, priceTmp, nameTmp);
- addElemToList(list, prod);
- }
- fclose(file);
- }
- /** \brief Stworzenie gniazda.
- *
- * Funkcja zwraca deskryptor pliku jako wynik funkcji socket(). Jesli operacja sie nie udala zwracamy wiadomosc i zatrzymujemy program.
- */
- int createSocket(){
- int serverFd;
- if ( (serverFd = socket(PF_INET, SOCK_STREAM, 0)) < 0){
- perror("Socket() - nie udalo sie");
- exit(1);
- }
- return serverFd;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- /**
- * \brief Sprawdzarka cen - server.
- *
- * Do dzialania naszego programu uzywamy protokolou Tcp. W argumencie wywolania podany nam zostaje port na ktorym
- * bedzie dzialal nasz program. Tworzymy gniazdo za pomoca funkcji socket(), nastepnie wykorzystujemy funcke bind()
- * oraz listen() i oczekujemy polaczenia. Wykorzystujemy accept() do nawiazania polączenia z klientem. Pobieramy z
- * pliku tekstowego "bazaDanych.txt" produkty do listy jednokierunkowej. Od klienta dostajemy wiadomosc.
- * Jesli to szesciocyfrowy kod kreskowy, to sprawdzamy czy posiadamy w naszej liscie produkt o danym kodzie.
- * Jesli tak, to odsylamy do klienta tablice znakow, ktora zawiwera wartosci skladowych tego produktu, w
- * przeciwnym wypadku, informacje o braku takowego produktu. Jesli klient przekazal nam wiadomosc "administrator"
- * to wysylamy do klienta wiadomosc "Panel administratora" razem z opcjami: 1.pokaz prodkuty, 2.dodaj produkt
- * 3. usun produkt, 4. wyjdz. Nastepnie w petli do-while oczekujemy na wiadomosc od klienta, jaka opcje wybral
- * i jesli wybral opcje 1, 2 lub 3 to realizujemy polecenie.
- *
- * Do wykonania 1 polecenia wykorzystujemy nasza funkcje sendList() i wysylamy do klienta nasza tablice zawierajaca
- * wszystkie dane produktow z listy.
- *
- * Do wykonania 2 polecania serwer wysyla do klienta wiadomosc "Podaj szesciocyfrowy kod kreskowy, cene i nazwe produktu" i oczekujemy
- * na odpowiedz. Ze zwroconegej tablicy znakow pobieramy do produktu prodTmp wartosci jej skladowych za pomoca funkcji getBarcode(), getPrice(), getName().
- * Nastepnie wykorzystujemy nasza funkcje addElemToList() do przekazania prodTmp do listy.
- *
- * Do wykonania 3 polecenia prosimy client o podanie szesciocyfrowego kodu kreskowego. Nastepnie wykorzystujemy funkcje removeProduct()
- * do usuniecia produktu o wskazanym kodzie.
- *
- * Zamykamy nasz polaczenie.
- */
- int main(int argc, int *argv[]){
- int serverFd, connectionFd;
- struct sockaddr_in servaddr;
- struct sockaddr_storage servStorage;
- socklen_t addrSize;
- char buffer[MAX_BUFFER +1];
- char result[MAX_BUFFER +1];
- if (argc != 2) {
- fprintf(stderr, "Usage: %s <Server Port>\n", argv[0]);
- exit(1);
- }
- int port = atoi(argv[1]);
- serverFd = createSocket();
- memset(&servaddr, 0 ,sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_port = htons(port);
- servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- if ( (bind(serverFd, (struct sockaddr *)&servaddr, sizeof(servaddr)) ) < 0){
- perror("bind() - nie udalo sie");
- exit(1);
- }
- if(listen(serverFd, MAX_BACKLOG) < 0){
- perror("listen() - nie udalo sie");
- exit(1);
- }
- else{
- system("clear");
- printf("Serwer aktywny. Oczekuje polaczenia...\n");
- }
- addrSize = sizeof(servStorage);
- if( (connectionFd = accept(serverFd, (struct sockaddr*)&servStorage, &addrSize) ) < 0 ){
- perror("accept() - nie udalo sie");
- exit(1);
- }
- if( (recv(connectionFd, buffer, MAX_BUFFER, 0)) < 0){
- perror("recv() - nie udalo sie \n");
- exit(1);
- }
- printf("Otrzymano kod: %s \n",buffer); // # 1 ODEBRANO WIADMOSC
- List *list = malloc(sizeof(List));
- getProdFromFileToList("bazaDanych.txt", list);
- int codeTmp;
- bool status;
- int optionInt;
- if(isAdmin(buffer)){ // 3.1 sprawdzamy wiadomosc
- clearTab(result, MAX_BUFFER);
- strcat(result, "Panel administratora. Wybierz operacje:\n1.pokaz produkty\n2.dodaj produkt\n3.usun produkt\n4.wyjdz\n");
- char* option = malloc(MAX_BUFFER * sizeof(char));
- if( (send(connectionFd, result, MAX_BUFFER, 0)) < 0){
- perror("send() - nie udalo sie \n");
- exit(1);
- }
- clearTab(option, MAX_BUFFER);
- do{
- if( (recv(connectionFd, option, MAX_BUFFER, 0)) < 0){
- perror("recv() - nie udalo sie \n");
- exit(1);
- }
- optionInt = atoi(option);
- char *tmpTab = malloc(MAX_BUFFER* sizeof(char));
- switch(optionInt){
- case 1 :{
- sendList(*list, &tmpTab);
- if( (send(connectionFd, tmpTab, MAX_BUFFER, 0)) < 0){
- perror("send() - nie udalo sie \n");
- exit(1);
- };
- break;
- }
- case 2: {
- clearTab(tmpTab, MAX_BUFFER);
- tmpTab = "Podaj szesciocyfrowy kod kreskowy, cene i nazwe produktu\n";
- if( (send(connectionFd, tmpTab, MAX_BUFFER, 0)) < 0){
- perror("send() - nie udalo sie \n");
- exit(1);
- }
- clearTab(result, MAX_BUFFER);
- if( (recv(connectionFd, result, MAX_BUFFER, 0)) < 0){
- perror("recv() - nie udalo sie \n");
- exit(1);
- }
- Product prodTmp;
- prodTmp.barcode = getBarcode(result, BARCODE_LEN);
- prodTmp.price = getPrice(result);
- prodTmp.name = getName(result);
- addElemToList(list, prodTmp);
- clearTab(&result, MAX_BUFFER);
- addToFile(*list);
- };break;
- case 3:{
- clearTab(tmpTab, MAX_BUFFER);
- tmpTab = "Podaj szesciocyfrowy kod kreskowy produktu ktory chcesz usunac: \n";
- if( (send(connectionFd, tmpTab, MAX_BUFFER, 0)) < 0){
- perror("send() - nie udalo sie \n");
- exit(1);
- }
- clearTab(result, MAX_BUFFER);
- if( (recv(connectionFd, result, MAX_BUFFER, 0)) < 0){
- perror("recv() - nie udalo sie \n");
- exit(1);
- }
- //printf("%s", result);
- codeTmp = atoi(result);
- removeProduct(list, codeTmp);
- };break;
- default: ;break;
- }
- }while(optionInt == 1 || optionInt == 2 || optionInt == 3);
- }else{ // JESLI NIE ADMIN !!!!!!!!!!!!!!!!!!!!!!!!!!1
- codeTmp = atoi(buffer);
- Product prodTmp;
- if(findProduct(list, codeTmp, &prodTmp )){ //jesli jest taki barKod
- snprintf(result, sizeof(result), "%i %.2f %s", prodTmp.barcode, prodTmp.price, prodTmp.name);
- }else{
- clearTab(result, MAX_BUFFER);
- strcat(result, "produkt o wskazanym kodzie kreskowym nie istnieje!");
- }
- if( (send(connectionFd, result, MAX_BUFFER, 0)) < 0){
- perror("send() - nie udalo sie \n");
- exit(1);
- }
- }
- if( (close(serverFd)) < 0){
- perror("close() - nie udalo sie \n");
- exit(1);
- }
- return(0);
- }
Advertisement
Add Comment
Please, Sign In to add comment