From b6f7823d632746be29b7a05e7b9ab04b14a450f8 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Sun, 10 Jun 2001 11:47:17 +0000 Subject: [PATCH] Iniziato a scrivere il server echo. Aggiunti un po' di placeholder per i processi --- main.tex | 1 + process.tex | 20 ++++- simpltcp.tex | 37 ++++----- sources/Makefile | 44 +++++++++++ sources/SimpleEchoTCPServer.c | 137 ++++++++++++++++++++++++++++++++++ sources/SockRead.c | 1 + sources/SockWrite.c | 1 + sources/wrappers.h | 10 ++- 8 files changed, 228 insertions(+), 23 deletions(-) create mode 100644 sources/Makefile create mode 100644 sources/SimpleEchoTCPServer.c diff --git a/main.tex b/main.tex index e2b93ad..6f26a6d 100644 --- a/main.tex +++ b/main.tex @@ -112,6 +112,7 @@ \include{app_b} \include{fdl} + % at the end put the bibliography diff --git a/process.tex b/process.tex index 52c1f40..51f0863 100644 --- a/process.tex +++ b/process.tex @@ -400,7 +400,6 @@ salvato sul file, in quanto viene inizializzato a zero al caricamento del programma. - \subsection{Allocazione della memoria per i programmi C} \label{sec:proc_mem_alloc} @@ -429,6 +428,11 @@ dinamica di spazio in memoria (in genere nello heap, usando la system call \texttt{sbrk}), solo che a questo punto sarà possibile usarlo solo in maniera indiretta attraverso dei puntatori. + +\subsection{Le funzioni \texttt{malloc}, \texttt{calloc}, \texttt{realloc} e + \texttt{free}} +\label{sec:proc_mem_malloc} + Le funzioni previste dallo standard ANSI C per la gestione della memoria sono quattro, i prototipi sono i seguenti: \begin{prototype}{stdlib.h}{void *calloc(size\_t size)} @@ -467,15 +471,24 @@ cos tipo. +\subsection{La funzione \texttt{alloca}} +\label{sec:proc_mem_alloca} - +\subsection{Le funzioni \texttt{brk} e \texttt{sbrk}} +\label{sec:proc_mem_sbrk} +\subsection{Il controllo della memoria virtuale} +\label{sec:proc_mem_sbrk} + +\section{Il controllo di flusso non locale} +\label{sec:proc_flux} + \section{La gestione di parametri e opzioni} -\label{sec:parameter_options} +\label{sec:proc_options} Il passaggio dei parametri e delle variabili di ambiente dalla riga di comando al singolo programma quando viene lanciato è effettuato attraverso le @@ -607,7 +620,6 @@ la gestione di queste ultime versione estesa di \texttt{getopt}. - \subsection{Le variabili di ambiente} \label{sec:proc_env_var} diff --git a/simpltcp.tex b/simpltcp.tex index de49446..5ee5a87 100644 --- a/simpltcp.tex +++ b/simpltcp.tex @@ -5,12 +5,6 @@ In questo capitolo riprenderemo le funzioni trattate nel precedente, usandole per scrivere una prima applicazione client/server che usi i socket TCP per una comunicazione in entrambe le direzioni. -L'applicazione sarà una implementazione elementare, ma completa, del servizio -\texttt{echo}. Si è scelto di usare questo servizio, seguendo lo Stevens, in -quanto esso costituisce il prototipo ideale di una generica applicazione di -rete; pertanto attraverso questo esempio potremo illustrare i fondamenti con i -quali si può costruire una qualunque applicazione di rete. - Inoltre prenderemo in esame, oltre al comportamento in condizioni normali, anche tutti i possibili scenari particolari (errori, sconnessione della rete, crash del client o del server durante la connessione) che possono avere luogo @@ -20,16 +14,25 @@ durante l'impiego di una applicazione di rete. \section{Il servizio \texttt{echo}} \label{sec:TCPsimp_echo} -Il servizio \texttt{echo} è uno dei servizi standard solitamente provvisti -direttamente dal superserver \texttt{inetd}, definito dall'RFC~862. Come dice -il nome il servizio deve semplicemente rimandare indietro i dati che gli -vengono inviati; l'RFC specifica che per il TCP una volta stabilita la -connessione ogni dato in ingresso deve essere rimandato in uscita, fintanto -che il chiamante non ha chiude la connessione; il servizio opera sulla porta -TCP numero 7. - -Nel nostro caso l'esempio sarà strutturato scrivendo un client che legge una -linea dallo standard input e la scrive sul server, il server leggerà una linea -dalla connessione e la riscriverà all'indietro; sarà compito del client +L'applicazione scelta come esempio sarà una implementazione elementare, ma +completa, del servizio \texttt{echo}. Il servizio \texttt{echo} è uno dei +servizi standard solitamente provvisti direttamente dal superserver +\texttt{inetd}, ed è definito dall'RFC~862. Come dice il nome il servizio deve +rimandare indietro sulla connessione i dati che gli vengono inviati; l'RFC +descrive le specifiche sia per TCP che UDP, e per il primo stabilisce che una +volta stabilita la connessione ogni dato in ingresso deve essere rimandato in +uscita, fintanto che il chiamante non ha chiude la connessione; il servizio +opera sulla porta 7. + +Nel nostro caso l'esempio sarà costituito da un client che legge una linea di +caratteri dallo standard input e la scrive sul server, il server leggerà una +linea dalla connessione e la riscriverà all'indietro; sarà compito del client leggere la risposta del server e stamparla sullo standard output. +Si è scelto di usare questo servizio, seguendo lo Stevens, perché costituisce +il prototipo ideale di una generica applicazione di rete in cui un server +risponde alle richieste di un client; tutto quello che cambia nel caso si una +applicazione più complessa è la elaborazione dell'input del client da parte +del server nel fornire le risposte in uscita. + + diff --git a/sources/Makefile b/sources/Makefile new file mode 100644 index 0000000..879aa31 --- /dev/null +++ b/sources/Makefile @@ -0,0 +1,44 @@ +# +# Simple Makefile to build examples +# +# C flags +CC=gcc +CFLAGS= -Wall +CFLADJ=-c + +OBJ = SockRead.o SockWrite.o + + +echod: SimpleEchoTCPServer.c $(OBJ) + $(CC) $(CFLAGS) SimpleEchoTCPServer.c $(OBJ) -o echod + +daytimed: ElemDaytimeTCPCuncServ.c + $(CC) $(CFLAGS) ElemDaytimeTCPCuncServ.c -o daytimed + +iterdaytimed: SimpleDaytimeTCPServer.c + $(CC) $(CFLAGS) SimpleDaytimeTCPServer.c -o iterdaytimed + +daytime: SimpleDaytimeTCPClient.c + $(CC) $(CFLAGS) SimpleDaytimeTCPClient.c -o daytime + +$(OBJ): wrappers.h + + + +.PHONY : clean +clean: + rm -f *~ + rm -f *.o + rm -f daytime + + + + + + + + + + + + diff --git a/sources/SimpleEchoTCPServer.c b/sources/SimpleEchoTCPServer.c new file mode 100644 index 0000000..35a2737 --- /dev/null +++ b/sources/SimpleEchoTCPServer.c @@ -0,0 +1,137 @@ +/**************************************************************** + * + * Program echo_tcp_server.c: + * Elementary TCP server for echo service (port 7) + * + * Author: Simone Piccardi + * Jun. 2001 + * + * Usage: echod + * + * $Id: SimpleEchoTCPServer.c,v 1.1 2001/06/10 11:47:17 piccardi Exp $ + * + ****************************************************************/ +/* + * Include needed headers + */ +#include /* predefined types */ +#include /* include unix standard library */ +#include /* IP addresses conversion utiliites */ +#include /* socket library */ +#include /* include standard I/O library */ +#include + +#include "wrappers.h" + +#define BACKLOG 10 +#define MAXLINE 256 + +/* Subroutine declaration */ +void usage(void); +void SockEcho(int sockfd); + +/* Program begining */ +int main(int argc, char *argv[]) +{ +/* + * Variables definition + */ + int list_fd, conn_fd; + pid_t pid; + struct sockaddr_in serv_add; + /* + * Input section: decode parameters passed in the calling + * Use getopt function + */ + int i; + opterr = 0; /* don't want writing to stderr */ + while ( (i = getopt(argc, argv, "h")) != -1) { + switch (i) { + /* + * Handling options + */ + case 'h': + printf("Wrong -h option use\n"); + usage(); + return(0); + break; + case '?': /* unrecognized options */ + printf("Unrecognized options -%c\n",optopt); + usage(); + default: /* should not reached */ + usage(); + } + } + /* *********************************************************** + * + * Options processing completed + * + * Main code beginning + * + * ***********************************************************/ + /* create socket */ + if ( (list_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("Socket creation error"); + exit(-1); + } + /* initialize address */ + memset((void *)&serv_add, 0, sizeof(serv_add)); /* clear server address */ + serv_add.sin_family = AF_INET; /* address type is INET */ + serv_add.sin_port = htons(13); /* daytime port is 13 */ + serv_add.sin_addr.s_addr = htonl(INADDR_ANY); /* connect from anywhere */ + /* bind socket */ + if (bind(list_fd, (struct sockaddr *)&serv_add, sizeof(serv_add)) < 0) { + perror("bind error"); + exit(-1); + } + /* listen on socket */ + if (listen(list_fd, BACKLOG) < 0 ) { + perror("listen error"); + exit(-1); + } + /* handle echo to client */ + while (1) { + /* accept connection */ + if ( (conn_fd = accept(list_fd, NULL, NULL)) < 0) { + perror("accept error"); + exit(-1); + } + /* fork to handle connection */ + if ( (pid = fork()) < 0 ){ + perror("fork error"); + exit(-1); + } + if (pid == 0) { /* child */ + close(list_fd); /* close listening socket */ + SockEcho(conn_fd); /* handle echo */ + exit(0); + } else { /* parent */ + close(conn_fd); /* close connected socket */ + } + } + /* normal exit, never reached */ + exit(0); +} +/* + * routine to print usage info and exit + */ +void usage(void) { + printf("Simple daytime server\n"); + printf("Usage:\n"); + printf(" daytimed [-h] \n"); + printf(" -h print this help\n"); + exit(1); +} +/* + * routine to handle echo for connection + */ +void SockEcho(int sockfd) { + char buffer[MAXLINE]; + int nread, nwrite; + + /* main loop, reading 0 char means client close connection */ + while ( (nread = SockRead(sockfd, buffer, MAXLINE)) != 0) { + nwrite = SockWrite(sockfd, buffer, nread); + } + return; +} diff --git a/sources/SockRead.c b/sources/SockRead.c index 749d767..5a7ba88 100644 --- a/sources/SockRead.c +++ b/sources/SockRead.c @@ -1,4 +1,5 @@ #include +#include ssize_t SockRead(int fd, void *buf, size_t count) { diff --git a/sources/SockWrite.c b/sources/SockWrite.c index ddeb4c7..466807c 100644 --- a/sources/SockWrite.c +++ b/sources/SockWrite.c @@ -1,4 +1,5 @@ #include +#include ssize_t SockWrite(int fd, const void *buf, size_t count) { diff --git a/sources/wrappers.h b/sources/wrappers.h index 70eb402..7120c43 100644 --- a/sources/wrappers.h +++ b/sources/wrappers.h @@ -5,7 +5,7 @@ * * Author: S. Piccardi * - * $Id: wrappers.h,v 1.1 2001/03/05 22:20:08 piccardi Exp $ + * $Id: wrappers.h,v 1.2 2001/06/10 11:47:17 piccardi Exp $ * ***************************************************************/ #include /* IPC semaphore declarations */ @@ -213,7 +213,7 @@ inline void UnlockFile(const char* path_name) * Return: the previous sigaction structure */ typedef void SigFunc(int); -SigFunc * Signal(int signo, SigFunc *func) +inline SigFunc * Signal(int signo, SigFunc *func) { struct sigaction new_handl, old_handl; new_handl.sa_handler=func; @@ -231,3 +231,9 @@ SigFunc * Signal(int signo, SigFunc *func) return (old_handl.sa_handler); } +/** + ** Defining prototypes for the all other functions + **/ +ssize_t SockRead(int fd, void *buf, size_t count); +ssize_t SockWrite(int fd, const void *buf, size_t count); + -- 2.30.2