distTLI/tcpserver.c
///////////////////////////////////////////////////////////////////////////////
// Filename: tcpserver.c
///////////////////////////////////////////////////////////////////////////////
// Purpose: show how to use TCP (this file: TCP server) (TLI version)
// uses tcpclient(.c) as TCP client
///////////////////////////////////////////////////////////////////////////////
// History:
// ========
//
// Date Time Name Description
// -------- -------- -------- ------------------------------------------------
// 96/02/26 13:52:19 muellerg: created
//
///////////////////////////////////////////////////////////////////////////////
// Feature test switches ///////////////////////////// Feature test switches //
/* NONE */
// System headers /////////////////////////////////////////// System headers //
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#ifndef sun
#include <strings.h>
#endif
#include <unistd.h>
#include <tiuser.h>
#include <sys/types.h>
#include <sys/socket.h>
// #include <sys/in.h>
#ifdef sun
// O_RDWR
#include <sys/fcntl.h>
#endif
#include <sys/wait.h>
// Local headers ///////////////////////////////////////////// Local headers //
#include "../common.h"
// Macros /////////////////////////////////////////////////////////// Macros //
/* NONE */
// File scope objects /////////////////////////////////// File scope objects //
/* NONE */
// External variables, functions, and classes ///////////// External objects //
int accept_call(int listenfd, struct t_call *callptr, char *name, int rwflag);
// Signal catching functions ///////////////////// Signal catching functions //
/* NONE */
// Structures, unions, and class definitions /////////////////// Definitions //
/* NONE */
// Functions and class implementation /// Functions and class implementation //
/*
* Read a stream socket one line at a time, and write each line back
* to the sender.
*
* Return when the connection is terminated.
*/
void
do_it(int sockfd)
{
int n;
char buffer[MAXLINE];
while(true)
{
n = readline(sockfd, buffer, MAXLINE);
if (n == 0)
return; // connection terminated
else
if (n < 0)
error.system("str_echo: readline error");
if (writen(sockfd, buffer, n) != n)
error.system("str_echo: writen error");
}
}
// Main /////////////////////////////////////////////////////////////// Main //
/*
* Example of server using TCP protocol. This program is lightly based on
* example programs in [Stev90]
*
* paramteters:
*
* argv[1]: port number to bind() & listen() to
*/
int
main(int argc, char *argv[])
{
error.set_program_name(argv[0]);
if(argc!=2)
{
cerr << "Usage: " << argv[0] << " port" << endl;
exit(EXIT_FAILURE);
}
// establish a function that changes the signalhandler
// to report child death so that they can be catched and
// zombie processes are avoided
#ifndef hpux
catch_children();
#endif
int tfd, newtfd, clilen, childpid;
struct sockaddr_in cli_addr, serv_addr;
struct t_bind req;
struct t_call *callptr;
int portnumber = -1;
// get port number
portnumber = atoi(argv[1]);
if(portnumber <1)
{
cerr << "illegal port number" << endl;
exit(EXIT_FAILURE);
}
// create a TCP transport endpoint.
if ( (tfd = t_open(DEV_TCP, O_RDWR, (struct t_info *) 0)) < 0)
{
error.warning("server: can't t_open %s", DEV_TCP);
exit(EXIT_FAILURE);
}
// Bind our local address so that the client can send to us.
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portnumber);
req.addr.maxlen = sizeof(serv_addr);
req.addr.len = sizeof(serv_addr);
req.addr.buf = (char *) &serv_addr;
req.qlen = 5;
if (t_bind(tfd, &req, (struct t_bind *) 0) < 0)
error.system("server: can't t_bind local address");
// Allocate a t_call structure for t_listen() and t_accept().
if ( (callptr = (struct t_call *) t_alloc(tfd, T_CALL, T_ADDR)) == NULL)
error.system("server: t_alloc error for T_CALL");
while(true)
{
// check for zombies
waitpid(WAIT_ANY, NULL, WNOHANG);
// Wait for a connection from a client process.
// This is an example of a concurrent server.
if (t_listen(tfd, callptr) < 0)
error.system("server: t_listen error");
if ( (newtfd = accept_call(tfd, callptr, DEV_TCP, 1)) < 0)
error.system("server: accept_call error");
if ( (childpid = fork()) < 0)
error.system("server: fork error");
else if (childpid == 0)
{ /* child process */
t_close(tfd); // close original endpoint
do_it(newtfd); // process the request
exit(EXIT_SUCCESS);
}
close(newtfd); /* parent process */
}
}