client.c :
codice:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "client.h"
int main(int argc,char* argv[])
{
int SocketDescriptor;
int Port;
int length;
char Buffer[2]="";
int i;
/* Verifico se ho inserito due parametri a linea di comando */
if ( argc == 3 )
{
/* Converto in intero il valore della porta */
Port=atoi(argv[2]);
/* Creo e connetto il socket */
SocketDescriptor=CreateSocket(argv[1],Port);
}
else
{
printf("Specifica Indirizzo IP e Porta\n");
exit(1);
}
for(;;)
{
/* Visualizzo comandi accettati dal client */
StampaCmdValidi();
length=read(0,Buffer,MAX_LEN);
write(1, "Comando scelto:\t", strlen("Comando scelto:\t"));
Buffer[length-1]='\0';
write(1, Buffer, MAX_LEN);
printf("len: %d\n", strlen(Buffer));
if (strlen(Buffer) == 2)
{
/* Il comando FM non viene inviato al server */
if (strcmp(Buffer, "FM") == 0)
{
write(1, "Container fermo. .\n", strlen("Container fermo. .\n"));
}
else
{
SendMessage(SocketDescriptor, Buffer);
}
}
else if (strlen(Buffer) != 2)
{
write(1, "Error: Comandi validi {ST, PO, UP, SX, DN, RX, FM}. .\n", strlen("Error: Comandi validi {ST, PO, UP, SX, DN, RX, FM}. .\n"));
}
/* Svuoto il buffer */
memset(Buffer, 0, MAX_LEN);
}
return 0;
}
void StampaCmdValidi()
{
write(1, "_________________________________________\n", strlen("_________________________________________\n"));
write(1, "COMANDI VALIDI:\n", strlen("COMANDI VALIDI:\n"));
write(1, "ST: Richiede le statistiche al server\n", strlen("ST: Richiede le statistiche al server\n"));
write(1, "PO: Richiede la posizione corrente del container\n", strlen("PO: Richiede la posizione corrente del container\n"));
write(1, "UP, DN, RX, SX: Comandi di spostamento\n", strlen("UP, DN, RX, SX: Comandi di spostamento\n"));
write(1, "FM. Questo comando NON viene inviato al server ed indica la necessitÃ_ di tenere il container fermo nel round corrente\n",
strlen("FM. Questo comando NON viene inviato al server ed indica la necessitÃ_ di tenere il container fermo nel round corrente\n"));
write(1, "_________________________________________\n", strlen("_________________________________________\n"));
}
void CloseSocket(int Socket)
{
close(Socket);
}
int CreateSocket(char *Address, int Port)
{
struct sockaddr_in *MyAddress;
int Socket;
int Error;
/* Indirizzo */
MyAddress = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
MyAddress->sin_family=AF_INET;
MyAddress->sin_port=htons(Port);
if (inet_aton(Address, &MyAddress->sin_addr) == 0)
{
printf("Indirizzo IP non valido\n");
exit(2);
}
/* Creazione socket */
Socket=socket(AF_INET,SOCK_STREAM,0);
//Connessione del socket. Esaminare errore per compiere azioni
//opportune in caso di errore.
Error=connect(Socket, (struct sockaddr*)MyAddress, sizeof(struct sockaddr_in));
if ( Error < 0 )
{
perror("\nConnessione fallita..: ");
exit(0);
}
return Socket;
}
void SendMessage(int Socket, char *Message)
{
printf("\nClient: %s\n",Message);
//Si puo' notare il semplice utilizzo di write:
//write(socket, messaggio, lunghezza messaggio)
if (write(Socket, Message, strlen(Message)) <0)
{
write(1, "\nImpossibile mandare il comando.\n", strlen("\nImpossibile mandare il comando.\n"));
//CloseSocket(Socket);
exit(1);
}
printf("\nMessaggio spedito con successo.\n");
}
server.c :
codice:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h>
#include <time.h>
#include "server.h"
int main(int argc, char* argv[])
{
int SocketDescriptor, ConnectedSocket;
char Buffer[MAX_LEN]="";
int ExitCond=0;
int length;
int N, T, i;
int Error;
SCALO *Scalo;
pthread_t *Threads;
int r;
fd_set fds;
struct timeval tv;
tv.tv_sec=0;
tv.tv_usec=0;
int s;
//static const char *CMD[] ={"UP", "DN", "SX", "DX"};
// Controllo che siano inseriti gli argomenti richiesti
if (argc != 3)
{
printf("Argomenti mancanti\n");
exit(1);
}
/* Dimensione scalo */
N=atoi(argv[1]);
/* Alloco un puntatore a pthread_t */
Threads=(pthread_t*)malloc(sizeof(Threads)*(N*N));
/* tempo del round */
T=atoi(argv[2]);
/* Inizializziamo lo scalo */
Scalo=InitScalo(N, T);
/* Stampo lo scalo */
StampScalo(Scalo);
printf("Num collisioni: %d\n", Scalo->NumCollisions);
printf("Num containers: %d\n", Scalo->NumContainers);
printf("Interv Round: %d\n", Scalo->IntervRound);
printf("Dim: %d\n", Scalo->Dim);
/* Creo e metto a disposizione il socket */
SocketDescriptor=InitSocket(4502);
printf("\nServer: Attendo connessioni...\n");
/* loop */
for(;;)
{
/* Tempo da attendere prima di passare al prossimo round */
for (i=1; i<=T; i++)
{
sleep(1);
sprintf(Buffer, "%d\n", i);
write(1, Buffer, sizeof(Buffer));
}
sleep(1);
printf("Attendo connessioni. . .\n");
if( (ConnectedSocket=accept(SocketDescriptor, NULL, NULL)) < 0 ) // La accept restituisce -1 alla seconda iterazione
{
printf("Err: %s", strerror(errno));
/* Significa che il socket è non bloccante e non ci sono connessioni in attesa */
if (errno == EWOULDBLOCK)
{
write(1, "Nessuna connessione in attesa. .\n", strlen("Nessuna connessione in attesa. .\n"));
}
/* Non ho alcuna richiesta però i thread devono continuare l'esecuzione
schiftando verso la fine dello scalo */
}
else /* Gestisci la richiesta del client */
{
/* Con questo risolvo il problema della read(essendo bloccante), ora faccio la read solo se c'è qualcosa
da leggere, quindi solo se scrivo qualcosa sul socket */
FD_ZERO(&fds);
FD_SET(ConnectedSocket, &fds);
r = select(ConnectedSocket+1,&fds, NULL, NULL, &tv);
if(r == 1)
{
length=read(ConnectedSocket, Buffer, MAX_LEN); // Questa read prima bloccava tutto
printf("Conn S dopo read%d\n", ConnectedSocket);
/* Controllo che il comando inviato sia corretto */
if ( (strlen(Buffer) == 2) &&
(strcmp(Buffer, "UP") == 0) ||
(strcmp(Buffer, "DN") == 0) ||
(strcmp(Buffer, "SX") == 0) ||
(strcmp(Buffer, "DX") == 0) )
{
/* Posso creare il thread ed eseguire il comando */
write(1, "Comando accettato -> Creazione thread. .\n", strlen("Comando accettato -> Creazione thread. .\n"));
pthread_create( (Threads+Scalo->NumContainers), NULL, Round, (void*)Buffer );
Scalo->NumContainers++; /* Incremento i containers */
}
else
{
write(1, "Comando non accettato. .\n", 25);
}
/* Svuoto il buffer */
memset(Buffer, 0, MAX_LEN);
}
}
}
return 0;
}
SCALO *InitScalo(int Dim, int IntervRound)
{
SCALO *Scalo;
int i, j;
Scalo=(SCALO*)malloc(sizeof(SCALO));
Scalo->Dim=Dim;
Scalo->IntervRound=IntervRound;
Scalo->NumContainers=0;
Scalo->NumCollisions=0;
Scalo->Pos_Containers=(POS_CONTAINER*)malloc(sizeof(POS_CONTAINER)*(Dim*Dim));
for (i=0; i<Dim*Dim; i++)
{
Scalo->Pos_Containers[i].PosX=0;
Scalo->Pos_Containers[i].PosY=0;
}
Scalo->Containers=(CONTAINER**)malloc(sizeof(CONTAINER*)*Dim);
for (i=0; i<Dim; i++)
{
Scalo->Containers[i]=(CONTAINER*)malloc(sizeof(CONTAINER)*Dim);
for (j=0; j<Dim; j++)
{
Scalo->Containers[i][j].PosX=i;
Scalo->Containers[i][j].PosY=j;
Scalo->Containers[i][j].Occupato=LIBERO;
}
}
return Scalo;
}
void StampScalo(SCALO *Scalo)
{
int i, j;
for (i=0; i<Scalo->Dim; i++)
{
for (j=0; j<Scalo->Dim; j++)
{
printf("%d ", Scalo->Containers[i][j].Occupato);
}
printf("\n");
}
}
int InitSocket(int Porta)
{
int Socket;
struct sockaddr_in *MyAddress;
/* Indirizzo */
MyAddress=(struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
MyAddress->sin_family=AF_INET; // Protocolli di rete
MyAddress->sin_port=htons(Porta);
MyAddress->sin_addr.s_addr=INADDR_ANY; // Consente di raggiungere il servizio da tutte le interfacce
//inet_aton("127.0.0.1", &myaddress->sin_addr);
/* Creo il socket */
Socket=socket(AF_INET, SOCK_STREAM, 0);
/* verifico se ritorna correttamente il socket descriptor */
if (Socket < 0)
{
perror("\nErrore nella creazione del socket: ");
exit(0);
}
/* Rendo il socket non bloccante in modo tale che se non ho una richiesta
* continuo la normale esecuzione dei thread */
fcntl(Socket, F_SETFL, O_NONBLOCK); // Setto il flag del fd come O_NONBLOCK
/* verifico se assegna correttamente l'indirizzo al canale di comunicazione */
if (bind(Socket, (struct sockaddr *)MyAddress, sizeof(struct sockaddr_in)) < 0 )
{
perror("\nErrore assegnazione indirizzo al socket..");
exit(1);
}
/* Pone il socket in attesa di una connessione, accetta al massimo
MAX_REQUEST richieste contemporanemente */
if (listen(Socket,5)<0)
{
perror("\nErrore listen al socket..");
exit(2);
}
return Socket;
}
void CloseSocket(int Socket)
{
close(Socket);
}
void *Round(void *arg)
{
char c=(char)arg;
pthread_mutex_lock(&mutex); /* Acquisisco il mutex */
/* Sezione critica */
printf("Il comando e' arrivato correttamente ed e': %c", c);
/* Fine sezione critica */
pthread_mutex_unlock(&mutex); /* Rilascio il mutex */
}