Article View: es.comp.os.linux.programacion
Article #7625Re: Código base en C de un servidor
From: J.A. Gutierrez
Date: Mon, 03 Feb 2003 12:29
Date: Mon, 03 Feb 2003 12:29
538 lines
11225 bytes
11225 bytes
Antonio Maestre Garc�a <anmaegar@quitararrakis.es> wrote:
: atenci�n. Lo que haga el servidor es ya cosa m�a... Seguro q debe haber por
: ah� un c�digo base. En principio quiero evitar programarlo yo o tener que
---------------------------------------------------------------------------
/*
* <spd@daphne.cps.unizar.es>
* Mon Apr 30 21:12:19 DST 2001
*
* :set tabstop=4
*
* Tested on:
*
* FreeBSD 4.2 ix86 gcc 2.95.2
* SunOS 5.7 Sparc gcc 2.95.2
* SunOS 5.8 Sparc WorkShop Compilers 5.0
* IRIX 6.2 mips MIPSpro Compilers: Version 7.2.1.2m
* Tru64 5.0 alpha Compaq C V6.1-011
* Linux RH 7.0 alpha gcc 2.96
* Linux RH 6.2 ix86 gcc 2.95.2
* HP-UX B.11.00 PA-RISC HP C/ANSI C Compiler B.11.01.06
*/
static char __ident[] = "@(#)SPDsoft, Wed May 2 18:55:37 DST 2001";
#define VERS_STR ((char*)&__ident[4])
#include <stdio.h>
#include <stdarg.h> /* va_ */
#include <stdlib.h> /* atoi */
#include <unistd.h> /* getpid */
#include <fcntl.h> /* getpid */
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>
#include <assert.h>
#ifdef __sgi
# define HAVE_DAEMONIZE
#endif
#ifndef HAVE_DAEMONIZE
/* _daemonize(3C) flags */
#define _DF_NOFORK 0x1 /* don't fork */
#define _DF_NOCHDIR 0x2 /* don't chdir to / */
#define _DF_NOCLOSE 0x4 /* close no files */
int my_daemonize(int flags, int fd1, int fd2, int fd3);
#define _daemonize my_daemonize
#endif
#define HAVE_SETSID 1 /* irix, linux, solaris */
#define HAVE_STRERROR 1
#ifndef HAVE_STRERROR
# define strerror(e) sys_errlist[(e)]
#endif
#ifndef _SYSV_SIGNALS
# define _BSD_SIGNALS
#endif
#ifdef _BSD_SIGNALS
# define sigset signal
#endif
#define IPL 32
#define MAXS 100
#ifndef DEFAULT_TPORT
#define DEFAULT_TPORT 5004
#endif
/*
* Globals
*/
int done;
typedef struct {
char my_ip[IPL];
int port_d, port_s;
} server_data_struct;
server_data_struct server_data[MAXS];
typedef struct {
unsigned int port;
int debug;
char *logfile;
FILE *f;
} prefs_struct;
prefs_struct gprefs;
/*
* Prototypes
*/
void clean( int i );
void usage(char *name);
void debug_msg(const char *fmt, ...);
int decode_reg(unsigned char *buf, long nbytes, uint32_t *sum);
int decode_unreg(unsigned char *buf, long nbytes, uint32_t *sum);
int decode_list(unsigned char *buf, long nbytes, uint32_t *sum);
int send_list(int s);
/*
*/
#define request_is(s1,s2) ( (s1[0]==s2[0])&&\
(s1[1]==s2[1])&&\
(s1[2]==s2[2])&&\
(s1[3]==s2[3]) )
void usage(char *name)
{
fprintf(stderr, "usage: %s [-p port] [-l logfile] [-d] [-v]\n",name);
fprintf(stderr, "-d: debug\n");
fprintf(stderr, "-v: version\n");
exit(-1);
}
#define perror(e) debug_msg("%s (%s)\n", e, strerror(errno))
void debug_msg(const char *fmt, ...)
{
va_list vl;
if ( NULL != gprefs.f)
{
va_start(vl,fmt);
vfprintf(gprefs.f,fmt,vl);
va_end(vl);
fflush(gprefs.f);
}
}
int main(int argc, char *argv[])
{
#define BS 1000
double n=0;
unsigned long n_p=0;
long nbytes;
int s;
int sockfd=0;
int clientlen;
struct sockaddr_in server,
client;
int fd;
unsigned char buf[BS];
uint32_t sum;
unsigned char *req;
int err;
struct timeval tv;
fd_set mask,
rmask;
int nfound;
int maxfd;
int reuse=1;
int option;
gprefs.port=DEFAULT_TPORT;
gprefs.debug=0;
gprefs.logfile=NULL;
gprefs.f=stderr;
while ( (option=getopt(argc,argv,"hdp:l:v")) != EOF )
{
switch(option)
{
case 'p':
gprefs.port = (unsigned int) atoi(optarg);
break;
case 'l':
gprefs.logfile = optarg;
break;
case 'd':
gprefs.debug = 1;
break;
case 'v':
fprintf(stdout, "%s\n",VERS_STR);
exit(0);
break;
case 'h':
default:
usage(argv[0]);
break;
}
}
tv.tv_sec = 2;
tv.tv_usec = 500000;
memset(&server,0,sizeof(server));
if ( !gprefs.debug )
{
if ( -1 == _daemonize(_DF_NOCHDIR,
gprefs.f != NULL ? fileno(gprefs.f) : -1, -1,-1))
perror("Can't daemonize");
}
server.sin_family = AF_INET;
server.sin_port = htons(gprefs.port);
server.sin_addr.s_addr = htonl(INADDR_ANY);
if (
( SIG_ERR == sigset(SIGTERM, clean)) ||
( SIG_ERR == sigset(SIGINT, clean)) )
perror("signal");
if ( (s=socket(AF_INET,SOCK_STREAM,0)) == -1 )
{
perror("Can't get socket");
exit(1);
}
/* debug_msg("open socket %d\n", s);*/
if (setsockopt(s, SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(int)) == -1)
{
perror("setsockopt");
}
if( bind( s, (struct sockaddr *)&server, sizeof(server)) != 0 )
{
perror("bind failed");
exit(1);
}
/* debug_msg("bind to %d\n", ntohs(server.sin_port));*/
if ( listen( s, 5 ) != 0 )
{
perror("Can't listen");
exit(1);
}
debug_msg("PID %d listening on %d\n", getpid(), ntohs(server.sin_port));
if ( NULL != gprefs.logfile )
{
if ( NULL == ( gprefs.f = fopen(gprefs.logfile, "wb")))
{
perror(optarg);
gprefs.logfile = NULL;
}
}
done=0;
FD_ZERO(&mask);
FD_SET(s, &mask);
maxfd=s;
for(;!done;)
{
rmask=mask;
nfound=select(maxfd+1, &rmask, NULL, NULL, &tv);
if (nfound<0)
{
if ( EINTR == errno )
{
debug_msg("Interrupted system call\n");
done=1;
break;
}
/*
* An error occurred during the select, or
* the select timed out.
*/
if ( 0 != errno )
{
perror("select");
done=1;
}
}
if (nfound==0)
{
continue;
}
if (FD_ISSET(s, &rmask))
{
done=0;
debug_msg("%d accepting\n", getpid());
clientlen=sizeof(client);
if (
(sockfd = accept( s, (struct sockaddr *)&client,&clientlen))
< 0 )
{
if ( errno != EINTR )
{
perror("accept");
done=1;
}
else
{
debug_msg("accept interrupted\n");
done=1;
}
}
else
{
debug_msg("- %d: accepted from %s\n",
sockfd, inet_ntoa(client.sin_addr));
fflush(stderr);
FD_SET(sockfd, &mask);
if (sockfd > maxfd)
maxfd = sockfd;
FD_CLR(s, &rmask);
}
}
for ( fd=0; fd<=maxfd; fd++)
{
if (FD_ISSET(fd, &rmask))
{
nbytes = recv(fd,buf,sizeof(buf)-1,0);
if ( nbytes < 0 )
{
perror("read");
}
if ( nbytes <= 0 )
{
debug_msg("- %d: EOF\n", fd);
FD_CLR(fd,&mask);
if ( -1 == shutdown(fd,2))
perror("shutdown");
else
debug_msg("- %d: shutdown\n",fd);
if ( -1 == close(fd))
perror("close");
else
debug_msg("- %d: closed\n", fd);
done = 0;
continue;
}
req = (unsigned char *) buf;
debug_msg("- %d: received request (%.4s)\n", fd, buf);
/* [...] */
if (request_is(req,"QUIT"))
{
/* Quit */
write(fd,"OK ",6);
FD_CLR(fd,&mask);
if ( -1 == shutdown(fd,2))
perror("shutdown");
else
debug_msg("- %d: shutdown\n",fd);
if ( -1 == close(fd))
perror("close");
else
debug_msg("- %d: shutdown\n",fd);
}
else
{
debug_msg("- %d: Unknown request (%.4s)\n", fd, buf);
write(fd,"ERUNKN",6);
break;
}
fflush(stdout);
n += nbytes;
n_p += 1;
}
}
}
debug_msg("Rec: %.0f bytes, %lu packets\n",n,n_p);
for ( fd=maxfd; fd>0; fd--)
{
if ( -1 == shutdown(fd,2))
perror("shutdown");
else
debug_msg("fd %d shutdown\n",fd);
if ( -1 == close(fd))
perror("close");
else
debug_msg("fd %d closed\n",fd);
}
exit(errno);
return(errno); /* Keep compiler happy */
}
/************************************************************************/
void clean( int sig )
{
if ( sig != SIGSEGV)
{
if ( SIG_ERR == sigset(sig, clean))
perror("clean:signal");
debug_msg("%d a escaparrar (%d)\n", getpid(), sig);
fflush(stderr);
done=1;
}
}
/************************************************************************/
#ifndef HAVE_DAEMONIZE
int my_daemonize(int flags, int fd1, int fd2, int fd3)
{
int status=0;
int fd;
debug_msg("daemonizing\n");
if (!( flags & _DF_NOFORK ))
{
/* Fork and exit in the parent to disassociate from the
* current process group and become the leader of a new
* process group.
*/
if ( -1 == (status = fork()))
{
perror("cant fork");
exit(1);
}
else if ( status > 0 )
{
_exit(0);
}
#if HAVE_SETSID
setsid();
#endif
if ( -1 == (status = fork()))
{
perror("cant fork again");
exit(1);
}
else if ( status > 0 )
{
_exit(0);
}
}
#ifdef TIOCNOTTY
if ( 0 < (fd = open("/dev/tty", O_RDWR)))
{
if (ioctl(fd, TIOCNOTTY, NULL) < 0)
{
perror("can't disassociate from the terminal");
status=-1;
}
close(fd);
}
#endif /* TIOCNOTTY */
if (!(flags & _DF_NOCHDIR))
{
if (chdir("/.") < 0)
{
perror("can't chdir to /.");
status=-1;
}
}
if (!(flags & _DF_NOCLOSE))
{
long l;
int i;
l=sysconf(_SC_OPEN_MAX);
while(l-->0)
{
if ((l!=fd1)&&(l!=fd2)&&(l!=fd3))
close(l);
}
if ( -1 == ( i = open( "/dev/null", O_RDWR)))
{
perror("/dev/null");
status=-1;
}
else
{
if ((1!=fd1)&&(1!=fd2)&&(1!=fd3))
dup(i);
if ((2!=fd1)&&(2!=fd2)&&(2!=fd3))
dup(i);
}
}
return(status);
}
#endif
---------------------------------------------------------------------------
--
PGP and other useless info at \
http://www.cps.unizar.es/~spd/ \
finger://daphne.cps.unizar.es/spd \ Timeo Danaos et dona ferentes
ftp://ivo.cps.unizar.es/pub/ \ (Virgilio)
Technical Details
Message-ID:
<b1lnbd$8o0$1@news.unizar.es>Path:
arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!newsfeed.stanford.edu!bloom-beacon.mit.edu!news.rediris.es!bashful.rediris.es!news.unizar.es!not-for-mailReferences:
<3e3bbbab_1@news.arrakis.es>Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII
X-Google-Thread: f86c8,79de37df9f28b12c
X-Google-Attributes: gidf86c8,public
X-Google-ArrivalTime: 2003-02-03 03:44:50 PST
Path: arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!newsfeed.stanford.edu!bloom-beacon.mit.edu!news.rediris.es!bashful.rediris.es!news.unizar.es!not-for-mail
From: "J.A. Gutierrez" <spd@daphne.cps.unizar.es>
Newsgroups: es.comp.os.linux.programacion
Subject: Re: Código base en C de un servidor
Date: 3 Feb 2003 12:29:33 GMT
Organization: Rank
Lines: 538
Message-ID: <b1lnbd$8o0$1@news.unizar.es>
References: <3e3bbbab_1@news.arrakis.es>
NNTP-Posting-Host: daphne.cps.unizar.es
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
X-Trace: news.unizar.es 1044275373 8960 155.210.152.20 (3 Feb 2003 12:29:33 GMT)
X-Complaints-To: usenet@news.unizar.es
NNTP-Posting-Date: 3 Feb 2003 12:29:33 GMT
User-Agent: tin/1.4.5-20010409 ("One More Nightmare") (UNIX) (IRIX/6.2 (IP22))