Autore: Fabio Di Matteo
Ultima revisione: 13/08/2008
Si realizzerà ,in Posix C , un server concorrente (capace di accettare più connessioni) in grado di autenticare gli utenti, e di presentare un prompt con servizio di eco dei comandi e anche data/ora.
Si realizzerà anche un client capace di utilizzare il suddetto server.
Il codice è ben commentato, ma qualora si volessero avere più informazioni sull'argomento sarebbe consigliabile sfogliare i seguenti testi:
Avvio il client:
./client 192.168.1.11 utente password
output:
Indirizzo server---> 192.168.1.11 socket creato! Risposta del server: USER-OK Risposta dal server: PASS-OK Ci siamo loggati con successo. server-> time Risposta del server: Wed Aug 13 16:23:35 2008 server-> ecoooooo!!! Risposta del server: ecoooooo!!! server-> exit Risposta del server: exit Risposta del server: Connessione terminata correttamente.
server.c
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <stdlib.h> #define MAX 8000 char user[]="utente"; char pass[]="password"; int server(void) { char buff[MAX]; char localbuff[MAX]; struct sockaddr_in server; struct sockaddr_in client; int sd, temp_sd, i; //int address_size; socklen_t address_size ; unsigned short port = 9000; pid_t pid; /* Creiamo il socket e riempiamo i campi della struttura * server */ if ( (sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) printf("Errore nella craazione del server!\n"); server.sin_family = AF_INET; server.sin_port = htons(port); server.sin_addr.s_addr = INADDR_ANY; /* assegnamo al socket un processo tramite la funzione BIND */ if (bind(sd, (struct sockaddr *)&server, sizeof(server)) < 0) printf("Errore nella chiamata di sistema BIND!\n"); /* Mettiamolo in ascolto */ listen (sd, 20); address_size=sizeof(client); while(1) { if ((temp_sd= accept(sd, (struct sockaddr *)&client, &address_size)) < 0){ perror("Errore nella chiamata ACCEPT\n"); exit (-1); } if ((pid = fork()) < 0) { perror(" fork error\n"); exit(-1); } if (pid == 0) { /* sono nel figlio */ close(sd); /*Riceviaimo i dati dal client */ //Riceviamo il nome utente recv(temp_sd, buff, sizeof(buff),MSG_WAITALL); printf("Nome utente : %s\n", buff); //controlliamo il nome utente if (strcmp(buff,user)==0){ sprintf(buff,"%s","USER-OK"); send(temp_sd, buff, sizeof(buff), MSG_WAITALL); recv(temp_sd, buff, sizeof(buff), MSG_WAITALL); printf("Password -->%s\n",buff); if (strcmp(buff,pass)==0){ sprintf(buff,"%s","PASS-OK"); send(temp_sd, buff, sizeof(buff), MSG_WAITALL); printf("Autenticato.\n"); while (strcmp(buff, "exit")!=0){//qui siamo autenticati recv(temp_sd, buff, sizeof(buff), MSG_WAITALL); //se l'utente digita il comando "time" il server restituisce la data if (strcmp(buff,"time")==0){ time_t timeval; timeval = time(NULL); snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&timeval)); } send(temp_sd, buff, sizeof(buff), MSG_WAITALL); /*inserire altro codice per le funzionalita' * del server*/ } sprintf(buff,"%s", "Connessione terminata correttamente."); send(temp_sd, buff, sizeof(buff), MSG_WAITALL); close(temp_sd); }else{ sprintf(buff,"%s","PASS-BUD"); printf("Non autenticato.\n"); send(temp_sd, buff, sizeof(buff), MSG_WAITALL); close(temp_sd); } }else{ sprintf(buff,"%s","USER-BUD"); printf("Non autenticato.\n"); send(temp_sd, buff, sizeof(buff), MSG_WAITALL); close(temp_sd); } }else { /* sono nel padre */ close(temp_sd); } }//chiude while close(temp_sd); return 0; } int main(int argc, char* argv[]){ server(); return 0; }
client.c
#include<stdio.h> #include<sys/types.h> #include<sys/socket.h> #include<netdb.h> #include<netinet/in.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define MAX 8000 int client(char* indirizzo_server, char *user, char* pass){ int sd; struct sockaddr_in client; struct hostent *hp; unsigned short port = 9000; char buff[MAX]; char risp[MAX]; /* Dobbiamo riempire la struttura client ma prima * ci occorrono alcune * informazioni che ricaviamo appoggiandoci * alla struttura hp */ //solo per il debug printf("\n\n Indirizzo server---> %s\n", indirizzo_server); //-- hp = gethostbyname(indirizzo_server); bzero(&client, sizeof(client)); client.sin_family = AF_INET; client.sin_port = htons(port); client.sin_addr.s_addr =((struct in_addr*)(hp->h_addr))->s_addr; /* Creiamo il socket */ if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) printf("Errore nella creazione del socket!\n"); else printf("socket creato!\n"); /* connettiamoci all'host */ if (connect(sd, (struct sockaddr *)&client, sizeof(client)) < 0){ printf("Errore di connessione!\n"); return -1; } /* Inviamo lo user */ sprintf(buff,"%s", user); send(sd, buff, sizeof(buff), MSG_WAITALL); /*riceviamo la risposta per lo user, se esiste chiede la password * con la stringa USER-OK*/ recv(sd, buff, sizeof(buff), MSG_WAITALL); sprintf(risp, "%s",buff); printf("Risposta del server: %s\n", risp); if (strcmp(risp,"USER-OK")==0){ //se l'utente è stato accettato, invio la password sprintf(buff,"%s",pass); send(sd, buff, sizeof(buff), MSG_WAITALL); //la risposta alla password recv(sd, buff, sizeof(buff), MSG_WAITALL); sprintf(risp,"%s",buff); printf("Risposta dal server: %s\n\n",risp); if (strcmp(risp,"PASS-OK")==0){ printf("Ci siamo loggati con successo.\n"); /*siamo autenticati, mettere qui sotto le altre * istruzioni*/ char cmd[80];//per il prompt dei comandi while (strcmp(risp,"exit")!=0){ printf("server-> ");scanf("%s",cmd); sprintf(buff, "%s", cmd); send(sd,buff,sizeof(buff),MSG_WAITALL); recv(sd, buff, sizeof(buff), MSG_WAITALL); sprintf(risp,"%s",buff); printf("Risposta del server: %s\n",risp); } recv(sd, buff, sizeof(buff), MSG_WAITALL); sprintf(risp,"%s",buff); printf("Risposta del server: %s\n",risp); }else{ printf("Password errata, il server ci ha sbattuti fuori.\n"); close(sd); } }else{ if (strcmp(buff, "USER-BUD")==0){ printf("Il server ci ha sbattuti fuori.\n"); close(sd); }else{ printf("Altro errore inatteso.\n"); close(sd); } } close(sd); return EXIT_SUCCESS; } int main (int argc, char *argv[]) { client(argv[1],argv[2],argv[3]); return 0; }
CPP = gcc all: $(CPP) server.c -o server $(CPP) client.c -o client clean: rm server rm client