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