Code:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <errno.h>
#include <error.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <signal.h>
const int PORT_SERVER = 6440; /* portul folosit */
const int CLIENTI_MAXIM = 3; /* nr maxim de clienti acceptati */
const int INTERVAL = 30; /* timp */
extern int errno; /* eroare returnata */
int nr = 0; /* numar de clienti */
int port; /* portul*/
struct operation request; /* cererea primita de server */
int sockfd, newsockfd, frlen, servlen;
int magic;
struct itimerval itv;
struct operation
{
int number1;
int number2;
int number3;
int number4;
int number5;
};
void genereaza_numar()
{
srand(time(NULL));
magic = rand() % 1001;
}
/*functie de tratare a semnalelor*/
void semnal (int nr_semnal)
{
if (nr_semnal == SIGCHLD)
{
wait(NULL);
nr--; /*s-a pierdut un client*/
printf("\nA iesit clientul %d!\n", nr+1);
printf("\n");
fflush(stdout);
return;
}
}
/* handler-ul semnalului SIGALRM */
void alarma()
{
printf("Generam un nou numar aleator...");
genereaza_numar();
printf("Numarul generat este %d\n", magic);
fflush(stdout);
/* setam handler-ul din nou */
if(signal(SIGALRM, alarma) == SIG_ERR)
{
perror("Eroare la signal()!\n");
exit(errno);
}
setitimer(ITIMER_REAL, &itv, 0);
}
/*operatiile pentru fiecare client*/
void doprocessing(int sock)
{
char mesaj[100];
if( nr == 0)
printf("S-a conectat un client...Avem %d client\n", nr + 1);
else
printf("S-a conectat un client...Avem %d clienti\n", nr + 1);
fflush(stdout);
sprintf(mesaj, "SERVER>Sunteti clientul cu numarul %d.\nSERVER>Introduceti cele 5 numere(0..1000):", nr + 1);
/* trimitem mesajul de intampinare */
if(send(newsockfd, mesaj, strlen(mesaj),0) != strlen(mesaj))
{
/* Eroare! */
shutdown(newsockfd, 2);
exit(errno);
}
/* am realizat conexiunea, asteptam mesajul... */
bzero (&request, sizeof(struct operation));
printf ("Asteptam cererea...\n");
fflush (stdout);
/* citirea mesajului */
int nrbytes = recv (newsockfd, &request, sizeof(struct operation), 0);
/*incercam sa citim datele de la client*/
if (nrbytes <= 0)
{
perror ("Eroare la read() de la client.\n");
close (newsockfd); /* inchidem conexiunea cu clientul */
}
/*verificam integritatea datelor*/
if (nrbytes < sizeof(struct operation))
{
perror ("Date primite incomplet\n");
close (newsockfd);
}
request.number1 = ntohl(request.number1);
request.number2 = ntohl(request.number2);
request.number3 = ntohl(request.number3);
request.number4 = ntohl(request.number4);
request.number5 = ntohl(request.number5);
printf ("Cerere primita... \n In curs de rezolvare: %d %d %d %d %d \n",
request.number1, request.number2, request.number3, request.number4, request.number5);
/* rezolvarea cererii */
int a=0;
int b=0;
int c=0;
int d=0;
int e=0;
int min=0;
int result=0;
/* diferenta dintre numarul magic si numerele primite */
if (magic >= request.number1)
a = magic - request.number1;
else
a = request.number1 - magic;
if (magic >= request.number2)
b = magic - request.number2;
else
b = request.number2 - magic;
if (magic >= request.number3)
c = magic - request.number3;
else
c = request.number3 - magic;
if (magic >= request.number4)
d = magic - request.number4;
else
d = request.number4 - magic;
if (magic >= request.number5)
e = magic - request.number5;
else
e = request.number5 - magic;
printf("\n Diferentele numerelor sunt: %d %d %d %d %d\n", a, b, c, d, e);
/* verificare care numar este mai aproape de numarul magic */
if (a > b)
min = b;
else
min = a;
if (min > c)
min = c;
if (min > d)
min = d;
if (min > e)
min = e;
printf(" Diferenta minima este: %d\n", min);
printf(" a= %d, b= %d, c= %d, d= %d, e= %d\n", a, b, c, d, e);
/*selectam numarul care este mai apropiat de numarul magic*/
if(min == a)
result = request.number1;
else
if (min == b)
result = request.number2;
else
if (min == c)
result = request.number3;
else
if (min == d)
result = request.number4;
else
result = request.number5;
//printf("result = %d\n", result);
//printf("TEST %d\n", magic);
printf("Numarul cel mai apropiat de cel random a fost: %d\n", result);
result = htonl(result);
if (min == 0)
{
printf("***********************************************************************\n");
fflush(stdout);
printf("Clientul cu nr %d a ghicit numarul(%d)!\n", nr + 1, magic);
printf("***********************************************************************\n");
fflush(stdout);
sprintf(mesaj, " SERVER>Ai ghicit numarul!(%d)\n", magic);
}
else
{
printf("***********************************************************************\n");
printf("Clientul cu nr %d s-a apropiat de numarul generat %d cu o diferenta de %d\n", nr + 1, magic, min);
printf("***********************************************************************");
fflush(stdout);
sprintf(mesaj, " SERVER>Nu ai ghicit numarul!(%d)\nSERVER>Te-ai apropiat de numarul generat cu o diferenta de %d\n", magic, min);
}
if(send(newsockfd, mesaj, strlen(mesaj),0) != strlen(mesaj))
{
shutdown(newsockfd, 2);
exit(errno);
}
/* returnam rapunsul clientului */
if (send (newsockfd, &result, sizeof(int),0) <= 0)
{
shutdown(newsockfd, 2);
perror ("Eroare la write() catre client.\n");
}
else
printf ("\nTrasmitere cu succes.\n\n");
/* am terminat cu acest client, inchidem conexiunea */
close (newsockfd);
}
/*programul principal*/
int main (int argc, char * argv[])
{
struct sockaddr_in server , from; /* structurile folosite de server si client */
int port; /* portul */
int pid; /* Process ID from fork() */
/* setare port in cazul specificarii explicite */
if (argc > 1)
{
port = atoi(argv[1]);
}
else
port = PORT_SERVER;
genereaza_numar();
printf("Numarul generat este %d\n", magic);
/* setam intervalul de generare a unui numar aleatoriu la 20 secunde */
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = INTERVAL;
itv.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &itv, 0);
/*tratarea semnalele*/
if (signal (SIGCHLD, semnal) == SIG_ERR)
{
perror("signal()");
exit(errno);
}
/* asociem semnalului SIGALRM un handler */
if(signal(SIGALRM, alarma) == SIG_ERR)
{
perror("Eroare la signal()!\n");
exit(errno);
}
/* cream un socket */
sockfd = socket(AF_INET, SOCK_STREAM,0);
if (sockfd <0)
{
perror("Eroare la socket().");
exit(1);
}
frlen = sizeof (from);
servlen = sizeof (server);
/* pregatim structurile de date */
bzero (&server, servlen);
bzero (&from, frlen);
/* umplem structura folosita de server */
server.sin_family = AF_INET; /* stabilirea familiei de socket-uri */
server.sin_addr.s_addr = htonl (INADDR_ANY); /* acceptam orice adresa */
server.sin_port = htons (port); /* utilizam un port utilizator */
/* atasam socketul */
if (bind (sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr)) == -1)
{
perror ("Eroare la bind().\n");
exit(1);
}
/* punem serverul sa asculte daca vin clienti sa se conecteze */
if (listen (sockfd, 3) == -1)
{
perror ("Eroare la listen().\n");
exit(1);
}
printf ("Asteptam la portul %d...\n", port);
fflush (stdout);
/*servim in mod concurent clientii*/
while (1)
{
newsockfd = accept(sockfd, (struct sockaddr *) &from, &frlen);
if (newsockfd < 0)
{
perror("Eroare la accept().\n");
exit(1);
}
/* Verificam daca am ajuns la numarul maxim de clienti */
char mesaj[100];
if (nr == CLIENTI_MAXIM)
{
perror("Numar maxim de clienti atins.\n");
sprintf(mesaj, "Numarul maxim de clienti permisi pentru conectare a fost deja atins!\nIncercati mai tarziu!\n");
if(send(newsockfd, mesaj, strlen(mesaj),0) != strlen(mesaj))
{
/* Eroare! */
shutdown(newsockfd, 2);
exit(errno);
}
continue;
}
/* Cream procesul copil*/
pid = fork();
if (pid < 0)
{
perror("Eroare la fork().\n");
exit(1);
}
if (pid == 0)
{
/* Procesul parcurs de client */
close(sockfd);
doprocessing(newsockfd);
exit(0);
}
else
{
close(newsockfd);
}
nr++;
}
}