From d6c366b7f155596fb6cb3ed2dc631cc54e8b42e3 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Fri, 2 Jan 2004 21:32:08 +0000 Subject: [PATCH] Materiale dimenticato e la versione preliminare del server echo implementato con poll. --- html/gapil.html | 9 +- listati/select_echod.c | 57 ++++++++++ sources/Makefile | 3 + sources/poll_echod.c | 253 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 321 insertions(+), 1 deletion(-) create mode 100644 listati/select_echod.c create mode 100644 sources/poll_echod.c diff --git a/html/gapil.html b/html/gapil.html index 312ab56..383c48c 100644 --- a/html/gapil.html +++ b/html/gapil.html @@ -252,7 +252,7 @@

- Versione corrente: 491 pagine. + Versione corrente: 499 pagine.

@@ -266,10 +266,17 @@ + 26 - dicembre - 2003
Inserito esempio di server + basato sull'I/O multiplexing. Ristrutturato il capitolo sui file + avanzati scorporando in una sezione a parte l'I/O multiplexing, + e inserendo alcuni esempi per pselect. Creata una terza + parte per le appendici. +

8 - novembre - 2003
Corretta tabella sbagliata al capitolo 5, completata la sezione sull'uso dell'I/O multiplexing sul lato client ed iniziata la versione server, inserita la trattazione della funzione shutdown. +

21 - settembre - 2003
Completato il capitolo sui socket elementari, e corretti numerosi errori. Revisione della diff --git a/listati/select_echod.c b/listati/select_echod.c new file mode 100644 index 0000000..d06b14e --- /dev/null +++ b/listati/select_echod.c @@ -0,0 +1,57 @@ + ... + memset(fd_open, 0, FD_SETSIZE); /* clear array of open files */ + max_fd = list_fd; /* maximum now is listening socket */ + fd_open[max_fd] = 1; + /* main loop, wait for connection and data inside a select */ + while (1) { + FD_ZERO(&fset); /* clear fd_set */ + for (i = list_fd; i <= max_fd; i++) { /* initialize fd_set */ + if (fd_open[i] != 0) FD_SET(i, &fset); + } + while ( ((n = select(max_fd + 1, &fset, NULL, NULL, NULL)) < 0) + && (errno == EINTR)); /* wait for data or connection */ + if (n < 0) { /* on real error exit */ + PrintErr("select error"); + exit(1); + } + if (FD_ISSET(list_fd, &fset)) { /* if new connection */ + n--; /* decrement active */ + len = sizeof(c_addr); /* and call accept */ + if ((fd = accept(list_fd, (struct sockaddr *)&c_addr, &len)) < 0) { + PrintErr("accept error"); + exit(1); + } + fd_open[fd] = 1; /* set new connection socket */ + if (max_fd < fd) max_fd = fd; /* if needed set new maximum */ + } + /* loop on open connections */ + i = list_fd; /* first socket to look */ + while (n != 0) { /* loop until active */ + i++; /* start after listening socket */ + if (fd_open[i] == 0) continue; /* closed, go next */ + if (FD_ISSET(i, &fset)) { /* if active process it*/ + n--; /* decrease active */ + nread = read(i, buffer, MAXLINE); /* read operations */ + if (nread < 0) { + PrintErr("Errore in lettura"); + exit(1); + } + if (nread == 0) { /* if closed connection */ + close(i); /* close file */ + fd_open[i] = 0; /* mark as closed in table */ + if (max_fd == i) { /* if was the maximum */ + while (fd_open[--i] == 0); /* loop down */ + max_fd = i; /* set new maximum */ + break; /* and go back to select */ + } + continue; /* continue loop on open */ + } + nwrite = FullWrite(i, buffer, nread); /* write data */ + if (nwrite) { + PrintErr("Errore in scrittura"); + exit(1); + } + } + } + } + ... diff --git a/sources/Makefile b/sources/Makefile index b669397..f2c6beb 100644 --- a/sources/Makefile +++ b/sources/Makefile @@ -76,6 +76,9 @@ echod: TCP_echod.c sechod: select_echod.c $(CC) $(CFLAGJ) $(CFLAGS) $^ -o $@ +pechod: poll_echod.c + $(CC) $(CFLAGJ) $(CFLAGS) $^ -o $@ + daytimed: TCP_cunc_daytimed.c $(CC) $(CFLAGJ) $^ -o $@ diff --git a/sources/poll_echod.c b/sources/poll_echod.c new file mode 100644 index 0000000..bf2774e --- /dev/null +++ b/sources/poll_echod.c @@ -0,0 +1,253 @@ +/* poll_echod.c + * + * Copyright (C) 2003 Simone Piccardi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/**************************************************************** + * + * Program poll_echod + * Elementary TCP server for echo service (port 7) using poll + * + * Author: Simone Piccardi + * Dec. 2003 + * + * Usage: echod -h give all info + * + * $Id: poll_echod.c,v 1.1 2004/01/02 21:32:08 piccardi Exp $ + * + ****************************************************************/ +/* + * Include needed headers + */ +#include /* system limits */ +#include /* predefined types */ +#include /* include unix standard library */ +#include /* IP addresses conversion utiliites */ +#include /* socket library */ +#include /* include standard I/O library */ +#include +#include /* syslog system functions */ +#include /* signal functions */ +#include /* error code */ +#include /* error strings */ +#include +#define _XOPEN_SOURCE +#include /* poll function definition */ + +#include "macros.h" +#include "Gapil.h" + +#define BACKLOG 10 +#define MAXLINE 256 +int demonize = 1; /* daemon use option: default is daemon */ +int debugging = 0; /* debug info printing option: default is no debug */ +/* Subroutines declaration */ +void usage(void); +void PrintErr(char * error); +/* Program beginning */ +int main(int argc, char *argv[]) +{ +/* + * Variables definition + */ + int waiting = 0; + int compat = 0; + struct sockaddr_in s_addr, c_addr; + socklen_t len; + char buffer[MAXLINE]; + struct pollfd *poll_set; + int list_fd, fd; + int max_fd, nread, nwrite; + int i, n = 256; + /* + * Input section: decode parameters passed in the calling + * Use getopt function + */ + opterr = 0; /* don't want writing to stderr */ + while ( (i = getopt(argc, argv, "hdicw:n:")) != -1) { + switch (i) { + /* + * Handling options + */ + case 'h': + printf("Wrong -h option use\n"); + usage(); + return(0); + break; + case 'i': + demonize = 0; + break; + case 'c': + compat = 1; + break; + case 'd': + debugging = 1; + break; + case 'w': + waiting = strtol(optarg, NULL, 10); + break; + case 'n': + n = strtol(optarg, NULL, 10); + break; + case '?': /* unrecognized options */ + printf("Unrecognized options -%c\n",optopt); + usage(); + default: /* should not reached */ + usage(); + } + } + /* *********************************************************** + * + * Options processing completed + * + * Main code beginning + * + * ***********************************************************/ + /* Main code begin here */ + if (compat) { /* install signal handler */ + Signal(SIGCHLD, HandSigCHLD); /* non restarting handler */ + } else { + SignalRestart(SIGCHLD, HandSigCHLD); /* restarting handler */ + } + /* create socket */ + if ( (list_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("Socket creation error"); + exit(1); + } + /* initialize address */ + memset((void *)&s_addr, 0, sizeof(s_addr)); /* clear server address */ + s_addr.sin_family = AF_INET; /* address type is INET */ + s_addr.sin_port = htons(7); /* echo port is 7 */ + s_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* connect from anywhere */ + /* bind socket */ + if (bind(list_fd, (struct sockaddr *)&s_addr, sizeof(s_addr)) < 0) { + perror("bind error"); + exit(1); + } + /* release privileges and go daemon */ + if (setgid(65534) !=0) { /* first give away group privileges */ + perror("cannot give away group privileges"); + exit(1); + } + if (setuid(65534) !=0) { /* and only after user ... */ + perror("cannot give away user privileges"); + exit(1); + } + if (demonize) { /* go daemon */ + openlog(argv[0], 0, LOG_DAEMON); /* open logging */ + if (daemon(0, 0) != 0) { + perror("cannot start as daemon"); + exit(1); + } + } + /* main body */ + if (listen(list_fd, BACKLOG) < 0 ) { + PrintErr("listen error"); + exit(1); + } + if (waiting) sleep(waiting); + /* initialize all needed variables */ + poll_set = (struct pollfd *) malloc(n * sizeof(struct pollfd)); + max_fd = list_fd; /* maximum now is listening socket */ + for (i=0; i