Il mio problema è molto semplice vorrei far girare un programma client/server che esegue le seguenti istruzioni:
-il client richiede l'ora e la data
-il server recupera l'informazione dal S.O. e la invia al client
-il client stampa la risposta del server su stdout
Il programma completo mi è stato fornito come esempio dal professore. Il mio problema è che non riesco a mandarlo in esecuzione.
PROGRAMMA LATO CLIENT - daytime_it_client.c
PROGRAMMA LATO SERVER - daytime_it_sercer.ccodice:#include "basic.h" int main(int argc, char **argv) { int sockd, n; char recvline[MAXLINE + 1]; struct sockaddr_in servaddr; if ( argc != 2 ) /*controlla numero degli argomenti */ err_quit("utilizzo: daytime_tcp_client <IPaddress>"); if ( (sockd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) /* crea il socket */ err_sys("errore in socket"); bzero(&servaddr, sizeof(servaddr)); /* azzera servaddr */ servaddr.sin_family = AF_INET; /* assegna il tipo di indirizzo */ servaddr.sin_port = htons(SERV_PORT); /* assegna la porta del server */ if ( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0 ) err_quit("errore in inet_pton per %s", argv[1]); /* assegna l'indirizzo del server prendendolo dalla riga di comando. L'indirizzo è una stringa e deve essere convertito in intero in network byte order. */ if ( connect(sockd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 ) err_sys("errore in connect"); /* apre la connessione con il server */ while ( (n = read(sockd, recvline, MAXLINE)) > 0 ) { /* legge dal socket fino a quando non trova l'EOF */ recvline[n] = 0; /* aggiunge il carattere di terminazione */ if (fputs(recvline, stdout) == EOF) err_sys("errore in fputs"); /* stampa il contenuto di recvline sullo standard output */ } if (n < 0) err_sys("errore in read"); exit(0); }
codice:#include "basic.h" int main(int argc, char **argv) { int listensd, connsd; struct sockaddr_in servaddr; char buff[MAXLINE]; time_t ticks; if( (listensd = socket(AF_INET, SOCK_STREAM, 0)) < 0) /* crea il socket */ err_sys("errore in socket"); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* il server accetta connessioni su qualsiasi indirizzo */ servaddr.sin_port = htons(SERV_PORT); /* numero di porta del server */ if( (bind(listensd, (SA *) &servaddr, sizeof(servaddr))) < 0) err_sys("errore in bind"); /* assegna l'indirizzo al socket */ if( listen(listensd, LISTENQ) < 0 ) err_sys("errore in listen"); /* trasforma il socket in passivo */ for ( ; ; ) { if( (connsd = accept(listensd, (SA *) NULL, NULL)) < 0) err_sys("errore in accept"); /* accetta una connessione con un client */ ticks = time(NULL); /* legge l'orario con la system call time */ snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks)); /* scrive in buff l'orario nel formato ottenuto da ctime. snprintf impedisce l'owerflow del buffer. */ if( write(connsd, buff, strlen(buff)) != strlen(buff) ) err_sys("errore in write"); /* scrive sul socket di connessione il contenuto di buff */ if( close(connsd) == -1 ) /* chiude la connessione */ err_sys("errore in close"); } }
basic.h
contiene include dei principali header file di sistema necessari per programmmi su reti:
ERROR.Ccodice:/* Header file di base per tutti gli esempi del corso */ /* Include header file di sistema attinenti alla programmazione con i socket e dichiarazioni e definizioni comuni a tutti gli esempi */ #ifndef __basic_h #define __basic_h /* include dei principali header file di sistema */ #include <sys/types.h> /* tipi di dati di sistema */ #include <sys/socket.h> /* dichiarazioni funzioni base su socket */ #include <sys/time.h> /* timeval{} per la select() */ #include <time.h> /* timespec{} per la pselect() */ #include <netinet/in.h> /* definizioni degli indirizzi dei socket */ #include <arpa/inet.h> /* funzioni inet(3) */ #include <errno.h> /* definizione di errno */ #include <fcntl.h> /* utilizzato per I/O nonbloccante */ #include <netdb.h> /* definizioni di macro e costanti attienti il network */ #include <signal.h> /* definizioni di handler di segnali */ #include <stdio.h> /* funzioni di I/O standard */ #include <stdlib.h> /* funzioni della libreria standard */ #include <string.h> /* funzioni ANSI C per manipolazione di stringhe */ #include <sys/stat.h> /* for S_xxx file mode constants */ #include <sys/uio.h> /* usato per iovec{} e readv/writev */ #include <unistd.h> /* usato da sysconf */ #include <sys/wait.h> /* usato da wait() */ #include <sys/un.h> /* utilizzato per socket Unix domain */ #include <sys/select.h> /* definizione di select() */ #include <poll.h> /* definizione di poll() */ #include <strings.h> /* funzioni non ANSI C su stringhe */ #include <sys/ioctl.h> /* usato per ioctl */ /* ------------------------------------------------------------------------- */ /* dichiarazioni delle funzioni di gestione degli errori */ void err_sys(const char *, ...); /* errore fatale in una system call */ void err_quit(const char *, ...); /* errore fatale non in una system call */ void err_dump(const char *, ...); /* errore fatale in una system call con dump */ void err_ret(const char *, ...); /* errore non fatale in una system call */ void err_msg(const char *, ...); /* errore non fatale non in una system call */ /* ------------------------------------------------------------------------- */ /* dichiarazioni delle funzioni di lettura e scrittura su uno stream socket */ ssize_t writen(int fd, const void *vptr, size_t n); ssize_t readn(int fd, void *vptr, size_t n); ssize_t readline(int fd, void *vptr, size_t maxline); ssize_t my_read(int fd, char *ptr); /* ------------------------------------------------------------------------- */ /* definizioni di costanti e macro di uso comune */ #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define MAXLINE 1024 #define MAXSOCKADDR 128 #define BUFFSIZE 8192 #define LISTENQ 5 /* Dimensione del backlog della listen() */ #define SERV_PORT 9877 /* TCP and UDP client-servers */ #define SERV_PORT_STR "9877" /* TCP and UDP client-servers */ #define UNIXSTR_PATH "/tmp/unix.str" /* Unix domain stream cli-serv */ #define UNIXDG_PATH "/tmp/unix.dg" /* Unix domain datagram cli-serv */ #ifndef SHUT_RD #define SHUT_RD 0 /* shutdown in lettura */ #define SHUT_WR 1 /* shutdown in scrittura */ #define SHUT_RDWR 2 /* shutdown in lettura e scrittura */ #endif typedef struct sockaddr SA; #endif
contiene le definizioni delle funzioni di gestione degli errori
__________________________________codice:#include "basic.h" #include <stdarg.h> /* ANSI C header file */ #include <syslog.h> /* per syslog() */ int daemon_proc; /* set nonzero by daemon_init() */ /* tutte le funzioni utilizzano err_doit per stampare un messaggio di errore. Differiscono per come viene gestito il controllo del programma. */ static void err_doit(int, int, const char *, va_list); /* err_ret gestisce errori non fatali attinenti una chiamata di sistema. Stampa un messaggio e restituisce il controllo al programma principale. */ void err_ret(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(1, LOG_INFO, fmt, ap); va_end(ap); return; } /* err_sys gestisce errori fatali attinenti una chiamata di sistema. Stampa un messaggio e termina l'esecuzione del programma. */ void err_sys(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(1, LOG_ERR, fmt, ap); va_end(ap); exit(1); } /* err_sys gestisce errori fatali attinenti una chiamata di sistema. Stampa un messaggio, effettua un dump del core e termina l'esecuzione del programma. */ void err_dump(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(1, LOG_ERR, fmt, ap); va_end(ap); abort(); /* dump core and terminate */ exit(1); /* shouldn't get here */ } /* err_msg gestisce errori non fatali non attinenti una chiamata di sistema. Stampa un messaggio e restituisce il controllo al programma principale. */ void err_msg(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(0, LOG_INFO, fmt, ap); va_end(ap); return; } /* err_sys gestisce errori fatali non attinenti una chiamata di sistema. Stampa un messaggio e termina l'esecuzione del programma. */ void err_quit(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(0, LOG_ERR, fmt, ap); va_end(ap); exit(1); } /* Stampa un messaggio e restituisce il controllo alla funzione chiamante. Per invocare la funzione bisogna specificare "errnoflag" per indicare il codice dell'errore che si è verificato e "level" per indicare il livello di syslog. */ static void err_doit(int errnoflag, int level, const char *fmt, va_list ap) { int errno_save, n; char buf[MAXLINE]; errno_save = errno; /* codice dell'errore che deve essere stampato */ #ifdef HAVE_VSNPRINTF vsnprintf(buf, sizeof(buf), fmt, ap); /* this is safe */ #else vsprintf(buf, fmt, ap); /* this is not safe */ #endif n = strlen(buf); if (errnoflag) snprintf(buf+n, sizeof(buf)-n, ": %s", strerror(errno_save)); strcat(buf, "\n"); if (daemon_proc) { syslog(level, buf); } else { fflush(stdout); /* se stdout and stderr coincidono */ fputs(buf, stderr); fflush(stderr); } return; }
Per mandare in esecuzione il programma apro due finestre di termale, in una scrivo:
mi da come errori:codice:gcc daytime_it_server.c error.c -o daytime_it_server
error.c: In function ‘err_doit’: error.c:108:3: warning: format not a string literal and no format arguments
Nella seconda finestra del terminale scrivo:
e mi riporta lo stesso errore di prima cioè:codice:gcc daytime_it_client.c error.c -o daytime_it_client
error.c: In function ‘err_doit’: error.c:108:3: warning: format not a string literal and no format arguments
nonostante gli errori continua e cerco di mandare in esecuzione:
dalla prima finestracodice:./daytime_it_server
dalla seconda finestracodice:./daytime_it_client
Dalla seconda finestra mi chiede: utilizzo: daytime_tcp_client <IPaddress>
Ora dovrei inserire qualcosa?E perchè mi dai quegli errori quando mando in compilazione?Scusare se mi sono dilungato spero possiate aiutarmi.
Saluti

Rispondi quotando