Nie pokazuje zawartości pliku w terminalu

0

Cześć!
Piszę taki mały i banalnie prosty programik klient - serwer pod linuxem w c i chcę żeby to tak działało: klient wpisuje nazwe pliku [to bedzie kodem towaru] i leci to do serwera, serwer sprawdza czy jest taki plik z nazwa i jesli jest to wraca ta informacja do klienta i klient ewentualnie wyswietla zawartosci tego pliku w swoim terminalu.

Dwa problemy jakie mam:

  1. nazwa pliku [pobrana przez klienta] jest w tablicy i nie wiem jak tą tablicę wysłać do serwera - tak się domyślam, że o to chodzi
  2. nie wiem jak z powrotem z serwera przekazać do klienta całą zawartość pliku aby to klient wyświetlił tą zawartość.

Generalnie program to ma być taka mini aplikacja do sprawdzenia cen towarów. Unikalne kody towarów to będą odddzielne pliki [wiem, że to lipna "baza danych" ale nic lepszego nie przychodziło mi do głowy :) ].

Klient:

/* proces klienta */

#include <netdb.h> 
#include <string.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/un.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define SIZE sizeof(struct sockaddr_in)

int main()
{
    int sockfd;
    char rc;
    char nazwaPliku[256];

    struct sockaddr_in server = {AF_INET, 7000};

    /* przeksztalc i zapamietaj adres ip serwera */
    server.sin_addr.s_addr = inet_addr("127.0.0.1");

    /* ustaw punkt koncowy transportu: */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket call failed");
        exit(1);
    }

    /* polacz gniazdo z adresem serwera: */
    if (connect(sockfd, (struct sockaddr *)&server, SIZE) == -1)
    {
        perror("connect call failed");
        exit(1);
    }

    /* wysylaj i odbieraj informacje od serwera: */
    for(rc = '\n'; ; )
    {
        if (rc == '\n')
            printf("********************************************************************\n");
            printf("* Podaj kod towaru aby sprawdzić jego nazwe i cenę, q kończy pracę *\n");
            printf("********************************************************************\n");

            scanf("%s", nazwaPliku);

            if (nazwaPliku == 'q')
            {
                printf("Program konczy prace...\n");
                exit(0);
            }

        send(sockfd, &nazwaPliku, 1, 0);

        if (recv(sockfd, &rc, 1, 0) > 0)
            printf("%c", rc);
        else
        {
            printf("server has died.\n");
            close(sockfd);
            exit (1);
        }
    }
}

Serwer:

/* proces serwera */

#include <netdb.h> 
#include <string.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/un.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define SIZE sizeof(struct sockaddr_in)

void catcher(int sig);
int newsockfd;

int main()
{
    printf("Serwer jest gotowy aby przyjac zapytanie...\n");

    int sockfd;
    char nazwaPliku[256];
    int jedenZnak;
    FILE *wp;

    /* zainicjuj gniazdo internetowe z numerem portu 7000
     * i adres lokalny, okreslany jako INADDR_ANY
     */
    struct sockaddr_in server = {AF_INET, 7000, INADDR_ANY};
    static struct sigaction act;

    act.sa_handler = catcher;
    sigfillset(&(act.sa_mask));
    sigaction(SIGPIPE, &act, NULL);

    /* ustaw punkt koncowy transportu: */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket call failed");
        exit(1);
    }

    /* zwiaz adres serwera z punktem koncowym */
    if (bind(sockfd, (struct sockaddr *)&server, SIZE) == -1)
    {
        perror("bind call failed");
        exit(1);
    }

    /* zacznij nasluchiwac przychodzacych polaczen */
    if (listen(sockfd, 5) == -1)
    {
        perror("listen call failed");
        exit(1);
    }

    for( ; ; )
    {
        /* przyjmij polaczenie */
        if((newsockfd = accept(sockfd, NULL, NULL)) == -1)
        {
            perror("accept call failed");
            continue;
        }

        /* utworz proces potomny do pracy z polaczeniem */
        if (fork() == 0)
        {
            /* odbierz dane: */
            while (recv(newsockfd, &nazwaPliku, 1, 0) > 0)
            {
                /* wyszukiwanie pliku o podanej nazwie: */
                        if (nazwaPliku == 'q')
                        {
                            printf("Program konczy prace...\n");
                            exit(0);
                        }

                        if ((wp = fopen(nazwaPliku, "r")) == NULL)
                            {
                                printf("Brak towaru w bazie!\n");
                                exit(1);
                            }
                        // pokazuje zawartosc pliku na ekranie:
                            while ((jedenZnak = getc(wp)) != EOF)
                            {
                                putc(jedenZnak, stdout);
                            }
                            fclose(wp);

                send(newsockfd, &nazwaPliku, 1, 0);
            }

            /* gdy klient nie wysyla dluzej informacji gniazdo moze byc zamkniete
             * i proces potomny zakonczony  */

            close(newsockfd);
            exit (0);
        }
        /* rodzic nie potrzebuje newsockfd: */
        close(newsockfd);
    }
}

void catcher (int sig)
{
    close(newsockfd);
    exit (0);
}
1

Próbujesz wysłać tylko jeden znak o tu send(sockfd, &nazwaPliku, 1, 0); w 3 argumencie, spójrz na doku
http://linux.die.net/man/2/send oraz http://linux.die.net/man/2/recv
Z klienta normalnie wysyłasz
send(sockfd, (const void*)nazwaPliku, strlen(nazwaPliku), 0)
A w servie ładujesz plik do tablicy i robisz podobnie
send(sockfd, (const void*)danePlik, strlen(danePlik), 0)
Albo podziel sobie tablice na 2 pakiety.

0

Echhh... zmieniłem tak jak mówisz i to jest dobre rozwiązanie natomiast im dalej w las tym więcej drzew :)
Chyba przekombinowałem z tym algorytmem przechowywania informacji w pliku bo teraz jest sporo zachodu żeby to poodczytywać i poprzesyłać odpowiednio i potem znowu odczytać...

No bo tak:
a) teraz muszę chyba załadować ten plik do tablicy danePliku i to tak żeby później po przesłaniu z serwera do klienta otworzył się poprawnie - ze spacjami itd.
b) później trzeba odczytać znać po znaku z tej tablicy [i nie skorzystam z EOF tylko będę musiał szukać ostatniego znaku w tablicy??] żeby to wyświetlić
c) kiedy zamykać deskryptor do pliku? Z klienta czy serwera? plik otwierany jest w serwerze...
d) inne problemy zapisane jako komentarze w kodzie

Jeszcze raz proszę o "rzucenie okiem" i podpowiedź co ja tu schrzaniłem...

Klient:

/* proces klienta */

#include <netdb.h> 
#include <string.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/un.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define SIZE sizeof(struct sockaddr_in)

int main()
{
    int sockfd;
    char rc;
    char nazwaPliku[256];

    struct sockaddr_in server = {AF_INET, 7000};

    /* przeksztalc i zapamietaj adres ip serwera */
    server.sin_addr.s_addr = inet_addr("127.0.0.1");

    /* ustaw punkt koncowy transportu: */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket call failed");
        exit(1);
    }

    /* polacz gniazdo z adresem serwera: */
    if (connect(sockfd, (struct sockaddr *)&server, SIZE) == -1)
    {
        perror("connect call failed");
        exit(1);
    }

    /* wysylaj i odbieraj informacje od serwera: */
    for(rc = '\n'; ; )
    {
        if (rc == '\n')
            printf("********************************************************************\n");
            printf("* Podaj kod towaru aby sprawdzić jego nazwe i cenę, q kończy pracę *\n");
            printf("********************************************************************\n");

            scanf("%s", nazwaPliku);

            if (nazwaPliku == 'q')
            {
                printf("Program konczy prace...\n");
                exit(0);
            }

        // wysyla nazwe wpisana przez uzytkownika do serwera aby sprawdzic czy istnieje taki plik:
        send(sockfd, &nazwaPliku, strlen(nazwaPliku), 0);

        // odbiera dane z serwera i wyswietla je na ekranie:
        // trzeba tu przeniesc ten kod z serwera ale trzeba jeszcze rozbic tablice plikowa
        // na pojedyncze znaki tak aby dzialalo to z petla "jedenZnak"

        if (recv(sockfd, void * danePliku, strlen(danePliku), 0) > 0)
            printf("%c", rc);
        else
        {
            printf("server has died.\n");
            close(sockfd);
            exit (1);
        }
    }
}

Serwer:

/* proces serwera */

#include <netdb.h> 
#include <string.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/un.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define SIZE sizeof(struct sockaddr_in)

void catcher(int sig);
int newsockfd;

int main()
{
    printf("Serwer jest gotowy aby przyjac zapytanie...\n");

    int sockfd;
    char nazwaPliku[256];
    char danePliku[256];
    int jedenZnak;
    FILE *wp;

    /* zainicjuj gniazdo internetowe z numerem portu 7000
     * i adres lokalny, okreslany jako INADDR_ANY
     */
    struct sockaddr_in server = {AF_INET, 7000, INADDR_ANY};
    static struct sigaction act;

    act.sa_handler = catcher;
    sigfillset(&(act.sa_mask));
    sigaction(SIGPIPE, &act, NULL);

    /* ustaw punkt koncowy transportu: */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket call failed");
        exit(1);
    }

    /* zwiaz adres serwera z punktem koncowym */
    if (bind(sockfd, (struct sockaddr *)&server, SIZE) == -1)
    {
        perror("bind call failed");
        exit(1);
    }

    /* zacznij nasluchiwac przychodzacych polaczen */
    if (listen(sockfd, 5) == -1)
    {
        perror("listen call failed");
        exit(1);
    }

    for( ; ; )
    {
        /* przyjmij polaczenie */
        if((newsockfd = accept(sockfd, NULL, NULL)) == -1)
        {
            perror("accept call failed");
            continue;
        }

        /* utworz proces potomny do pracy z polaczeniem */
        if (fork() == 0)
        {
            /* odbierz dane: */
            while (recv(newsockfd, &nazwaPliku, strlen(nazwaPliku), 0) > 0)
            {
                /* wyszukiwanie pliku o podanej nazwie: */
                        if (nazwaPliku == 'q')
                        {
                            printf("Program konczy prace...\n");
                            exit(0);
                        }

                        if ((wp = fopen(nazwaPliku, "r")) == NULL)
                            {
                                printf("Brak towaru w bazie!\n");
                                exit(1);
                            }

                        // wysyla dane znalezionego pliku do klienta:
                        send(newsockfd, (const void*)danePliku, strlen(danePliku), 0);

                        /* pokazuje zawartosc pliku na ekranie ale ta sekcja powinna byc chyba w kliencie???
                         * i nie wiem czy wtedy z klienta czy z serwera zamykac deskryptor do pliku???
                         */
                            while ((jedenZnak = getc(wp)) != EOF)
                            {
                                putc(jedenZnak, stdout);
                            }
                            fclose(wp);
            }

            /* gdy klient nie wysyla dluzej informacji gniazdo moze byc zamkniete
             * i proces potomny zakonczony  */

            close(newsockfd);
            exit (0);
        }
        /* rodzic nie potrzebuje newsockfd: */
        close(newsockfd);
    }
}

void catcher (int sig)
{
    close(newsockfd);
    exit (0);
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0