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
codice:
#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); }
PROGRAMMA LATO SERVER - daytime_it_sercer.c
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:
codice:
/* 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
ERROR.C
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:
codice:
gcc daytime_it_server.c error.c -o daytime_it_server
mi da come errori:
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:
codice:
gcc daytime_it_client.c error.c -o daytime_it_client
e mi riporta lo stesso errore di prima cioè:
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:
codice:
./daytime_it_server
dalla prima finestra
codice:
./daytime_it_client
dalla seconda finestra
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