jump to navigation

C Socket Programming in the UNIX environment – part 5 12 dicembre 2007

Posted by fripp in C, GNU/Linux, Informatica, Networking, Programmazione, Sistemi Operativi, Unix.
Tags: , , , , , , ,
trackback

Ecco il codice di una semplicissima applicazione client-server che simula il servizio daytime. In maniera molto banale, il client si connette al server per ottenere data e ora corrente.

Ecco il codice del server:

#include
#include
#include
#include
#include
#include
#include
#include
#include

#define BACKLOG 10

int main (int argc, const char * argv[]) {
int list_fd,conn_fd;
struct sockaddr_in serv_add;
char buffer[80];
time_t timeval;

//creiamo la socket
if((list_fd=socket(AF_INET,SOCK_STREAM,0))<0){ perror("socket creation error\n"); exit(-1); } //la funzione memset azzera la memoria riservata alla struttura serv_add memset((void*)&serv_add,0,sizeof(serv_add)); //inizializziamo la struttura in maniera opportuna serv_add.sin_family=AF_INET; //specifica che useremo il protocollo IPv4 serv_add.sin_port=htons(13); //specifichiamo la porta su cui si mette in ascolto il server //usiamo la htons per impostare il valore corretto in network byte order serv_add.sin_addr.s_addr=htonl(INADDR_ANY); //la funzione setsockopt permette di impostare delle opzioni per la socket che //si sta usando. //in particolare, questa chiamata alla funzione permette di riutilizzare la porta //della socket anche dopo che la connessione è stata chiusa. //senza la chiamata a questa funzione, alla chiusura della connessione la porta appena //usata non è momentaneamente disponibile, perchè risulta esser ancora allocata a livello kernel int yes=1; if(setsockopt(list_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int))<0){ perror("setsockopt\n"); exit(-1); } //facciamo il binding della socket con la struttura che descrive l'indirizzo if(bind(list_fd,(struct sockaddr*)&serv_add,sizeof(serv_add))<0){ perror("bind error\n"); exit(-1); } //mettiamo il server in ascolto sulla socket if(listen(list_fd,BACKLOG)<0){ perror("listen error\n"); exit(-1); } //all'interno del ciclo while il server accetta le connessioni //la funzione 'accept' restituisce la socket su cui il server gestirà la connessione //col client while(1){ struct sockaddr_in tmp; unsigned int addrlen=sizeof(tmp); memset((void*)&tmp,0,sizeof(tmp)); if((conn_fd=accept(list_fd,(struct sockaddr*)NULL,NULL))<0){ perror("accept error\n"); exit(-1); } //la funzione getpeername permette di ottenere informazioni sul client //la funzione prende come argomenti la socket di connessione, //una struttura di tipo sockaddr_in e un puntatore alla dimensione //in bytes della struttura getpeername(conn_fd,(struct sockaddr*)&tmp,&addrlen); //attraverso la funzione inet_ntoa trasformiamo l'indirizzo del client in una stringa in notazione decimale puntata printf("Client IP: %s\nClient port: %d\n",inet_ntoa(tmp.sin_addr),tmp.sin_port); timeval=time(NULL); //il server calcola la data corrente e la manda al client attraverso la funzione write snprintf(buffer,sizeof(buffer),"%.24s\r\n",ctime(&timeval)); //la funzione write prende come argomenti: //1) la socket di connessione //2) il buffer contenente le informazioni da trasmettere //3) la lunghezza del buffer in bytes //il secondo parametro della write è un void* if(write(conn_fd,buffer,strlen(buffer))<0){ perror("write error\n"); exit(-1); } //chiudiamo la connessione close(conn_fd); } return 0; }[/sourcecode] Ecco il codice del client: [sourcecode language="C"] #include
#include
#include
#include
#include
#include

int main (int argc, const char * argv[]) {
int sock_fd; //descrittore della socket
int nread;
struct sockaddr_in serv_add; //conterrà le informazioni relative al server
char buffer[80];
char indirizzo_server[]=”127.0.0.1″;

//crea la socket TCP
if( (sock_fd=socket(AF_INET,SOCK_STREAM,0))<0 ){ perror("Socket creation error\n"); return -1; } //inizializza l'indirizzo del server //azzeriamo la struttura che descrive la socket memset((void*)&serv_add,0,sizeof(struct sockaddr_in)); serv_add.sin_family=AF_INET; //address family inet IPv4 serv_add.sin_port=htons(13); //definiamo il numero di porta //in particolare la funzione htons converte //bytes in host order in bytes in network order //la funzione inet_pton converte una stringa "dotted decimal" in un indirizzo "utile" if( inet_pton(AF_INET,indirizzo_server,&serv_add.sin_addr) <= 0){ perror("Address creation error\n"); return -1; } //stabilisce la connessione if(connect(sock_fd,(struct sockaddr*) &serv_add,sizeof(serv_add))<0){ perror("Connection error"); return -1; } //legge le informazioni trasmesse dal server while((nread=read(sock_fd,buffer,80))>0){
buffer[nread]=0;
if(fputs(buffer,stdout)==EOF){
perror(“fputs error”);
return -1;
}
}

if(nread<0){ perror("Read error"); return -1; } close(sock_fd); return 0; }[/sourcecode] Possiamo notare come il server di cui ho postato il codice non è un server "concorrente", ma "iterativo". Ciò vuol dire che questo server è in grado di servire una sola richiesta alla volta. Per implementare un server concorrente è necessario saper gestire la crezione e l'esecuzione di processi e thread in concorrenza. Spero in futuro di poter parlare di questi argomenti (tempo permettendo!). Buona programmazione. (I file sorgente li trovate qui)

Annunci

Commenti»

1. Samuele Castrenzi - 14 dicembre 2007

Ciao, affinchè il server funzioni devi sostituire socket_fd con list_fd, altrimenti nemmeno compila.
Vedi sotto:

—–
int yes=1; if(setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int))<0){
^^^^^
list_fd
perror(“setsockopt\n”);
exit(-1);
}
——

Samuele

2. fripp - 14 dicembre 2007

Grazie per la segnalazione!

3. Greg - 3 marzo 2008

Ciao,
io qnd vado a compilare in windows ricevo un errore sull’include di arpa/inet.h…nn lo trova

mentre se compilo in linux (ubuntu aggiornato) mi da errori a cascata e immagino che la causa sia che non ho le librerie incluse….

dove posso trovarle?

grazie per l’aiuto!

4. fripp - 3 marzo 2008

E` normale che su windows non trovi arpa/inet.h. Secondo te perchè il post s’intitola “C socket programming in the Unix environment”? Da che mondo è mondo, windows non è un sistema Unix. Il fatto che su ubuntu ti dia errore è strano. Le librerie che servono devon esserci per forza.Che errori da?

5. Greg - 3 marzo 2008

Si pensavo che le librerie avrebbe dovuto trovarle in ogni caso….cmq su linux ho risolto grazie.

6. Sir Dark - 5 agosto 2008

bastava un sudo apt-get install build-essential credo.. comunque carina la guida 😉

7. gladiatore - 11 febbraio 2010

Ragazzi qualcuno mi può postare una chat client server in c per ovviamente in unix…..
(Aiutatemiiiiiiiiii!)


Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

%d blogger hanno fatto clic su Mi Piace per questo: