Client-server mit sockets



  • Hallo
    ich habe hier eine aufgabe aber ich habe keine ahnung wie ich es ergänzen soll:(

    Ein Server stellt ein Auktionsangebot
    bereit, auf das Clients bis zum Ende der
    Auktion bieten können. Die Clients
    erfragen vom Server den momentanen
    Stand des Gebots und geben dann ihr
    eigenes Gebot ab. Am Ende der Auktion
    werden die Clients über das Ergebnis
    informiert.

    realisierung muss so sein:
    Die Kommunikation des Servers mit den Clients erfolgt über TCP/IP-Sockets, der Server
    arbeitet dabei als paralleler Server. Für jeden Client, der an der Auktion teilnehmen will, wird
    im Elternprozess ein Kindprozess gestartet, der jeweils einen Client bedient.
    - Während der Auktion kann ein Client von seinem Serverprozess den aktuellen Stand
    (auktionsStruct) der Auktion abfragen und Gebote abgeben
    - Während der Auktion wartet ein Server-Kindprozess auf die Anfrage seines Clients, um dann
    den auktionsStruct abzuliefern. Dann wartet der Serverchildprozess auf ein neues Gebot des
    Client.
    ♦ Ist das neue Gebot des Client das momentane Höchstgebot, wird es im Struct
    auktionsStruct abgespeichert.
    ♦ Ist das neue Gebot des Client nicht das momentane Höchstgebot, wird es nicht
    abgespeichert.
    ♦ Danach wartet der Serverprozess wiederum auf die Anfrage des Client nach dem aktuellen
    Stand und er verarbeitet das neue Gebot.
    - Das timeChild überwacht die Endezeit der Auktion.
    ♦ Sobald die Zeit abgelaufen ist setzt Timechild flag = 0 und
    ♦ sendet dem Parentprozessen ein Signal.
    ♦ Danach beendet sich Timechild.
    - Mit einem Mechanismus, den Sie selbst festlegen dürfen, ist zu gewährleisten, dass die Clients
    das Auktionsende „ohne große Verzögerung“ erhalten. Jedenfalls müssen die Clients nicht erst
    ein neues Angebot abgeben, um das Auktionsende mitgeteilt zu bekommen.
    - Sobald die Clients flag = 0 entdecken, fordern sie kein neues Angebot an, sondern geben das
    Ende der Auktion ihren Childs bekannt indem sie den Server-Childprozessen ein
    Acknowledge (flag = 1000) senden. Dann beenden sich die Clients ordnungsgemäß.
    - Sobald die Server-Childprozesse das Acknowledge entdecken, beenden sie sich
    ordnungsgemäß.
    - Der Elternprozess des Servers wartet in seinem Signalhandler auf die Beendigung der Childprozesse, bevor er aufräumt und sich beendet.

    die quelcode von server,client und myfunction:

    server.c:
    #include "Server.h"
    // Globale Variablen für Semaphoren und Anzahl Kinder
    int mutex;
    int childNum = 0;
    // Zweck:              Handler fuer Signal SIGUSR1; Aufbeendigung der Kindprozesse
    //                            warten; SM freigen; Semaphore loeschen
    // Parameter: Signalnummer
    static void sigUsr1Handler(int signr)
    {
    
      //ERGAENZEN  
    
    }
    // Zweck:              Ausgabe des aktuellen Gebots
    // Parameter: Auktionsstrukt
    void printA(auktionsStruct * auktion)
    {
      // ergaenzen
    }
    // Zweck:              Auktion innerhalb von Server-Kindprozessen durchfuehren
    // Parameter:          sockfd:        kennung des verbundenen Sockets zum Client
    //                     auktion:       Strukt mit Gebot
    //                     num:           Nummer der Client-Server-Verbindung
    void auction(int sockfd, auktionsStruct * auktion, int num)
    {
            auktionsStruct *fauktion = (auktionsStruct*)malloc(sizeof(auktionsStruct));
            Writen(sockfd, &num, sizeof(num));                // Clientnummer an Client schicken
            for(;;)
            {
                   printA(auktion);                           // Auktionsdaten ausgeben
                   printf("\n");
                   // AuktionsStruct schicken
                   Writen(sockfd, auktion, sizeof(auktionsStruct));
                   // Gebot in fauktion empfangen
                   Readn(sockfd, fauktion, sizeof(auktionsStruct));
                   if(auktion->flag == 0)                     // Auktionsende?
                   {
                     // ergaenzen
                   }
                   else
                   {
                           // Gebot muss > Startgebot und AktuellesGebot sein
                           if(auktion->startGebot > fauktion->aktuellesGebot);
                           else if(auktion->aktuellesGebot < fauktion->aktuellesGebot)
                           {
                                  if(auktion->flag != 0)      // Auktionsende?
                                  {
                                     //ERGAENZEN  [cpp]
                                  }
                           }
                   }
            }
    }
    // Zweck:      Server fuer Auktion;
    //                     Initialisierung: Struct, SM, Semaphore, Handler
    //                     Kindprozess zur Zeit-ueberwachung anlegen
    //                     Ueber Socket Verbindung zu Clients aufnehmen;
    //                     pro Client einen Server-Kindprozess schaffen
    //                     Beendigung innerhalb des Sugnalhandlers
    int main(int argc, char **argv)
    {
            auktionsStruct * auktion;
            int    listenfd, connfd;
            pid_t childpid;
            socklen_t clilen;
    
            struct sockaddr_in cliaddr, servaddr;
            long hilfl;
            struct sigaction saUsr1;
            long now;
            pid_t ppid;
            // Anlegen und Einrichten eines Shared Memory
            auktion = initSM();
            // Einrichten der Semaphoren
            mutex = initSem();
            //V(mutex);                                            // Mutex freigeben?
            // AuktionsStruct initialisieren
            // ergaenzen
            // SIGUSR1 einrichten
            initHandler(SIGUSR1, saUsr1, sigUsr1Handler);
            // Socket anlegen und einrichten
            listenfd = Socket(AF_INET, SOCK_STREAM, 0);
               bzero(&servaddr, sizeof(servaddr));
               servaddr.sin_family = AF_INET;
               Inet_aton("127.0.0.1", &servaddr.sin_addr);
               servaddr.sin_port=htons(SERV_PORT);
            Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
            Listen(listenfd, LISTENQ);
            if((childpid = Fork()) == 0)                           // Kindprozess für Zeitabfrage
            {
             // ergaenzen
            }
            else if(childpid != (0 || -1))                         // Elternprozess
            {
                    for (childNum = 1;;childNum++)                 // Anzahl Kinder erhöhen
                    {
                            clilen = sizeof(cliaddr);
                            if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0)
                            {
                                      if (errno == EINTR)
                                               continue;           // weiter in Schleife for()
                                      else
                                               syserr("accept error");
                            }
                            if ( (childpid = Fork()) == 0)
                            {         // Kindprozess fuer Client anlegen
                                      // Im Kindprozess:Horchenden Socket schliessen
                                      Close(listenfd);
                                      // Auktionsvorgang
                                      auction(connfd, auktion, childNum);
                                      exit(0);
                            }
                            // Eltenprozess schliesst verbundenen Socket
                            Close(connfd);                                      }
                    exit(0);
            }
    }
    
    client.c:
    
    #include "Client.h"
    // Zweck:     Auktion in Client durchfuehren
    // Parameter: Kennung des Sockets
    void auction(int sockfd)
    {
           char gebot[MAXLINE];
            auktionsStruct * auktion = (auktionsStruct*)malloc(sizeof(auktionsStruct));
           // dynamischer Speicher?
           auktionsStruct * auktion;
           int ii = 0;
           int num;
           Readn(sockfd, &num, sizeof(num));                     // Clientnummer empfangen
           printf("Clientnummer:    %d\n\n", num);
           Readn(sockfd, auktion, sizeof(auktionsStruct));       // Auktionsdaten empfangen
           while(auktion->flag != 0)                             // solange Auktion nicht beendet
           {
            // ergaenzen:
            // Aktuellen Stand ausgeben
            // Neues Gebot erfragen und einlesen
            // Gebot wegschicken
            // auf aktuellen Stand warten
           }
           printf("Auktionsende\n\n");                           // Auktionsende
           printf("Clientnummer:            %d\n", num);
           printf("Höchstbietender Client: %d\n", auktion->hgClient);
           printf("Gebot:                   %ld\n\n", auktion->aktuellesGebot);
           // Acknowledge setzen und struct schicken
           auktion->flag = 1000;
           Writen(sockfd, auktion, sizeof(auktionsStruct));
           // free (auktionsstruct);
           exit(0);                                              // Client beenden
    }
    // Zweck:     Client fuer Auktion
    // Parameter: IP-Nummer des Servers
    int main(int argc, char **argv)
    {
           int   sockfd;
           struct sockaddr_in servaddr;
           // Socket anlegen und initialisieren
           sockfd = Socket(AF_INET, SOCK_STREAM, 0);
           if (argc != 2)
             syserr("Usage: client <IP Address>");
           bzero(&servaddr, sizeof(servaddr));
           servaddr.sin_family = AF_INET;
           servaddr.sin_port=htons(SERV_PORT);
           Inet_aton(argv[1], &servaddr.sin_addr);
           Connect(sockfd, (SA *) &servaddr, sizeof(servaddr));
           // Auktion durchfuehren
           auction(sockfd);
           exit(0);
    }
    
    myfunctions.c:
    
    #include "myfunctions.h"
    // Zweck:            Semaphoren initialisieren
    // Rueckgabewert:    Kennung
    int initSem(void)
    {
           int kennung;
           if((kennung = semget(IPC_PRIVATE, 1, 0660)) == -1)
                  printf("Fehler bei semget\n");
           if(semctl(kennung, 0, SETVAL, (int)1) == -1)
                  printf("Fehler bei semctl: init\n");
           return kennung;
    }
    // Zweck:            Semaphoren löschen
    // Parameter:        Kennung
    void destroySem(int kennung)
    {
           if(semctl(kennung, 0, IPC_RMID, 0) == -1)
                  printf("Fehler bei semctl: delete\n");
    }
    // Zweck:            Semaphoren benutzen
    // Parameter:        kennung=Kennung
    //                   operation=1 freigeben, =-1 anfordern
    void pv(int kennung, int operation)
    {
           static struct sembuf semaphor;
           semaphor.sem_op = operation;
           semaphor.sem_flg = SEM_UNDO;
           if(semop(kennung, &semaphor, 1) == -1)
                  printf("semop- Fehler\n");
    }
    // Zweck:            Signalhandler initialisieren
    // Parameter
    //     signr:        Signal
    //     sigaction:    Struktur für Handler
    //     handler:      Funktionsname des Handlers
    void initHandler (int signr, struct sigaction sa, void (*handler))
    {
       memset (&sa, 0,sizeof(sa)); /* mit 0 init*/
       sa.sa_handler = handler;
       sa.sa_flags= SA_NOCLDSTOP;
       if (sigaction(signr, &sa,NULL)== -1)
           printf("Kann Handler nicht einrichten \n");
    }
    // Zweck:     SM initialisieren
    // Rückgabe: Zeiger auf SM
    auktionsStruct* initSM(void)
    {
           auktionsStruct * auktion;
           if((kennung = shmget(IPC_PRIVATE, sizeof(auktionsStruct), 0660)) == -1)
           {
                  printf("Kann SM nicht anlegen\n");
           }
           if(( auktion = (auktionsStruct*)shmat(kennung, NULL, (SHM_R|SHM_W))) < 0)
           {
                  printf("Kann SM nicht anschliessen\n");
           }
           return auktion;
    }
    // Zweck:     SM loeschen
    // Parameter: Kennung
    void destroySM(int kennung)
    {
           if((shmctl(kennung, IPC_RMID, 0)) == -1)
                  printf("Fehler bei shmctl: delete\n");
    }
    

    Ich bin sehr dankbar falls jemand helfen könnte:)


Anmelden zum Antworten