/* echo-process.c * * Copyright (c) 2000 Sean Walton and Macmillan Publishers. Use may be in * whole or in part in accordance to the General Public License (GPL). * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*****************************************************************************/ /*** echo-process.c ***/ /*** ***/ /*** An echo server using processes for multiple, simultaneous connections.***/ /*****************************************************************************/ #include #include #include #include #include #include #include /*#include */ #include void PANIC(char* msg); #define PANIC(msg) { perror(msg); exit(-1); } /*--------------------------------------------------------------------*/ /*--- Signal capture: SIGCHLD ---*/ /*--------------------------------------------------------------------*/ void sig_handler(int sig) { if ( sig == SIGCHLD ) { int retval; printf("\nSIG_HANDLER: Waiting for child to finish ..."); wait(&retval); printf("Done.\n"); } } /*--------------------------------------------------------------------*/ /*--- Child - echo servlet ---*/ /*--------------------------------------------------------------------*/ void Child(void* arg) { char line[100]; int bytes_read; int client = *(int *)arg; bzero(line, 100); /* do {*/ bytes_read = recv(client, line, sizeof(line), 0); if ( bytes_read < 0 ) perror("Read socket"); send(client, line, bytes_read, 0); printf("CHILD: Sent response: %s\n", line); /* } while (strncmp(line, "bye\r", 4) != 0 || bytes_read < 0 );*/ close(client); printf("CHILD: connection closed ...\n"); /*exit(0);*/ } /*--------------------------------------------------------------------*/ /*--- main - set up server and wait for connections ---*/ /*--------------------------------------------------------------------*/ int main(void) { int sd; struct sigaction act; struct sockaddr_in addr; bzero(&act, sizeof(act)); act.sa_handler = sig_handler; act.sa_flags = SA_NOCLDSTOP; sigaction(SIGCHLD, &act, 0); if ( (sd = socket(PF_INET, SOCK_STREAM, 0)) < 0 ) PANIC("Socket"); printf("PARENT: socket created\n"); addr.sin_family = AF_INET; addr.sin_port = htons(9999); addr.sin_addr.s_addr = INADDR_ANY; if ( bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 ) PANIC("Bind"); printf("PARENT: Socket bound\n"); if ( listen(sd, 20) != 0 ) PANIC("Listen"); printf("PARENT: Listening ...\n"); while (1) { int client, pid, addr_size = sizeof(addr); printf("PARENT: Waiting for connection ...\n"); client = accept(sd, (struct sockaddr*)&addr, &addr_size); if ( client < 0 ) perror("Accept"); else { printf("PARENT: Connected: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); printf("PARENT: Forking ...\n"); if ( pid = fork() ) { printf("PARENT: PID %d ...\n", pid); close(client); printf("PARENT: Done\n"); } else { printf("CHILD: PID %d ...\n", pid); close(sd); printf("CHILD: Processing client ...\n"); Child(&client); printf("Child: Exiting\n"); exit(0); } } } return 0; }