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:)