Barra laterale

programmazione:c:server_e_client

Server e client

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:

Il client in azione

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.

Il server

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;
}

Il client

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;
 
}

Il makefile

CPP = gcc

all:
	$(CPP) server.c -o server 
	$(CPP) client.c -o client 

clean:
	rm server
	rm client

programmazione/c/server_e_client.txt · Ultima modifica: 18/04/2018 - 15:49 (modifica esterna)