Article View: es.comp.os.linux.programacion
Article #14480Re: Sockets y multiples conexiones.
From: J.A. Gutierrez
Date: Wed, 08 Nov 2000 00:00
Date: Wed, 08 Nov 2000 00:00
493 lines
13225 bytes
13225 bytes
Santiago Romero <sromero@escomposlinux.org> wrote:
: las conexiones entrantes. �tengo que hacer un vector para las
: conexiones y recorrerlo con un bucle? �usar el fork ese (que no
: s� usar) para duplicar el programa? :?
puedes hacer ambas cosas, incluso una tercera: lanzarlo
desde inetd.
: En fin, como A. Gutierrez anda por aqui, planteo mi pregunta en
: busca de ayuda ;)
Si todas las comunicaciones entrantes tienen que ser manejadas
por un mismo codigo ("mezcladas" unas con otras, vamos) probablemente
la solucion mas sencilla sea "select()"; aunque a base de forks
con pipes tambien se puede hacer.
Aqui tienes un par de ejemplos, aunque tendras que pulirlos
bastante:
-8<----serv-fork.c---------------------------------------------------------
#include <stdio.h>
#include <stdlib.h> /* atoi */
#include <unistd.h> /* getpid */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>
int s;
int kids=0;
int done;
void clean( int i );
void do_wait(int signal);
int main(int argc, char *argv[])
{
double n;
long n_p,nbytes;
int len;
int sockfd;
int clientlen;
int queue;
struct sockaddr_in server,
client;
FILE *fd;
char buf[10000];
char *myname;
char *host;
char *user;
char hostname[256];
struct hostent *hp;
unsigned int port;
int pid;
if (argc!=2)
{
printf( "use: %s port\n", argv[0] );
exit(1);
}
port = (unsigned int) atoi(argv[1]);
memset(&server,0,sizeof(server));
if (gethostname(hostname,sizeof(hostname)) < 0)
{
perror("gethostname: who am I ?");
exit(1);
}
if ( (hp=gethostbyname(hostname)) == NULL)
{
perror("gethostbyname: can't get an address");
exit(2);
}
server.sin_family = AF_INET;
/* server.sin_port=atoi(buf);*/
server.sin_port = htons(port);
/* server.sin_addr.s_addr = htonl(INADDR_ANY);*/
/* server.sin_addr.s_addr =inet_addr(argv[1]);*/
server.sin_addr.s_addr =
htonl( ((struct in_addr *)(hp->h_addr_list[0]))->s_addr );
queue=3;
if (( SIG_ERR == sigset(SIGTERM, clean)) ||
( SIG_ERR == sigset(SIGINT, clean)) ||
( SIG_ERR == sigset(SIGCHLD, do_wait))
)
perror("signal");
if ( (s=socket(AF_INET,SOCK_STREAM,0)) == -1 )
{
perror("socket");
exit(1);
}
if( bind( s, (struct sockaddr *)&server, sizeof(server)) != 0 )
{
perror("bind");
exit(1);
}
if ( listen( s, queue ) != 0 )
{
perror("listen");
exit(1);
}
for(done=0; !done; )
{
fprintf(stderr,"%d accepting\n", getpid());
if( ( sockfd = accept( s, 0, 0 ) ) < 0 )
if ( errno != EINTR )
{
perror("accept");
break;
}
else
continue;
switch( pid = fork())
{
case -1:
perror("fork");
break;
case 0:
n = 0;
n_p = 0;
nbytes = recv(sockfd,buf,sizeof(buf),0);
buf[nbytes]=0x00;
write(sockfd,"ack\r\n",5);
while(nbytes>0)
{
fprintf(stdout,"MSG: \"%s\"\n",buf);
fflush(stdout);
n += nbytes;
n_p += 1;
nbytes = recv(sockfd,buf,sizeof(buf),0);
buf[nbytes]=0x00;
write(s,"ack\r\n",5);
}
printf("Rec: %.0f bytes %.0ld packets\n",n,n_p);
fprintf(stderr,"die %d\n", getpid());
close( s );
exit(0);
break;
default:
fprintf(stderr, "%d spawned %d\n", ++kids, pid );
fflush(stderr);
break;
}
}
while ( kids > 0 )
{
sigpause(SIGCLD);
sighold(SIGCLD);
}
if ( s != 0 )
{
if ( -1 == close(s))
perror("close");
}
exit(errno);
}
/************************************************************************/
void clean( int sig )
{
if ( SIG_ERR == sigset(sig, clean))
perror("clean:signal");
fprintf(stderr,"%d a escaparrar (%d)\n", getpid(), sig);
done=1;
}
void do_wait(int sig)
{
int st;
int wpid;
wpid = wait ( &st );
fprintf(stderr, "wait: died %d\n", wpid);
if (WIFSTOPPED(st))
{
fprintf(stderr,"stoped %d\n", WSTOPSIG(st));
}
else if(WIFEXITED(st))
{
fprintf(stderr, "do_wait: %d exit with %d\n", wpid, WEXITSTATUS(st));
}
else if(WIFSIGNALED(st))
{
fprintf(stderr,"signaled %d\n", WTERMSIG(st));
}
if(st&0200)
fprintf(stderr, "core dumped\n");
fprintf(stderr, "do_wait: died %d\n", wpid);
fprintf(stderr, "nkids %d\n", --kids);
fflush(stderr);
sigset(SIGCHLD, do_wait);
}
-8<----serv-fork.c---------------------------------------------------------
-8<----serv-select.c-------------------------------------------------------
#include <stdio.h>
#include <stdlib.h> /* atoi */
#include <unistd.h> /* getpid */
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>
int s;
int kids=0;
int done;
void clean( int i );
int main(int argc, char *argv[])
{
double n=0;
long n_p=0,nbytes;
int len;
int sockfd=0;
int clientlen;
struct sockaddr_in server,
client;
int fd;
char buf[10000];
char *myname;
char *host;
char *user;
char hostname[256];
struct hostent *hp;
unsigned int port;
int pid;
struct timeval tv;
fd_set mask,
rmask;
int nfound;
int maxfd;
if (argc>2)
{
printf( "use: %s port\n", argv[0] );
exit(1);
}
if (argc==2)
port = (unsigned int) atoi(argv[1]);
else
port = 0;
tv.tv_sec = 2;
tv.tv_usec = 500000;
memset(&server,0,sizeof(server));
if (gethostname(hostname,sizeof(hostname)) < 0)
{
perror("gethostname: who am I ?");
exit(1);
}
if ( (hp=gethostbyname(hostname)) == NULL)
{
perror("gethostbyname: can't get an address");
exit(2);
}
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr =
htonl(INADDR_ANY);
/* htonl( ((struct in_addr *)(hp->h_addr_list[0]))->s_addr );*/
if (( SIG_ERR == sigset(SIGTERM, clean)) ||
( SIG_ERR == sigset(SIGINT, clean)) )
perror("signal");
if ( (s=socket(AF_INET,SOCK_STREAM,0)) == -1 )
{
perror("socket");
exit(1);
}
if( bind( s, (struct sockaddr *)&server, sizeof(server)) != 0 )
{
perror("bind");
exit(1);
}
fprintf(stderr,"bind to %d\n", ntohs(server.sin_port));
if ( listen( s, 5 ) != 0 )
{
perror("listen");
exit(1);
}
done=0;
FD_ZERO(&mask);
FD_SET(s, &mask);
maxfd=s;
for(;!done;)
{
if (0==sockfd)
fprintf(stderr,"waiting for connect(select)\n");
else
fprintf(stderr,"waiting for input(select)\n");
rmask=mask;
/* nfound=select(FD_SETSIZE, &rmask, NULL, NULL, &tv);*/
nfound=select(maxfd+1, &rmask, NULL, NULL, &tv);
fprintf(stderr,"select: %d\n", nfound);
if (nfound<0)
{
if ( EINTR == errno )
{
fprintf(stderr,"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)
{
fprintf(stderr,"Timeout %d\n",done);
continue;
}
if (FD_ISSET(s, &rmask))
{
done=0;
fprintf(stderr,"%d accepting\n", getpid());
clientlen=sizeof(client);
if (
(sockfd = accept( s, (struct sockaddr *)&client,&clientlen))
< 0 )
{
if ( errno != EINTR )
{
perror("accept");
done=1;
}
else
{
fprintf(stderr,"accept interrupted\n");
done=1;
}
}
else
{
fprintf(stderr,"accepted %d 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 )
{
fprintf(stderr,"EOF %d\n", fd);
FD_CLR(fd,&mask);
if ( -1 == close(fd))
perror("close");
else
{
fprintf(stderr,"%d closed\n", fd);
}
done = 1;
continue;
}
buf[nbytes]='\0';
write(fd,"ack\r\n",5);
fprintf(stdout,"MSG: \"%s\"\n",buf);
fflush(stdout);
n += nbytes;
n_p += 1;
}
}
}
printf("Rec: %.0f bytes %.0ld packets\n",n,n_p);
for ( fd=maxfd; fd>2; fd--)
{
if ( -1 == shutdown(fd,2))
perror("shutdown");
else
fprintf(stderr,"sockfd %d shutdown\n",fd);
if ( -1 == close(fd))
perror("close");
else
fprintf(stderr,"sockfd %d closed\n",fd);
}
exit(errno);
}
/************************************************************************/
void clean( int sig )
{
if ( SIG_ERR == sigset(sig, clean))
perror("clean:signal");
fprintf(stderr,"%d a escaparrar (%d)\n", getpid(), sig);
fflush(stderr);
done=1;
}
-8<----serv-select.c-------------------------------------------------------
--
PGP and other useless info at \ La ciencia-ficcion es
http://www.cps.unizar.es/~spd/ \ ese futuro en el que
finger://daphne.cps.unizar.es/spd \ lo seguro es que ya
ftp://ivo.cps.unizar.es/pub/ \ (F. Alfaro) no seremos jovenes
Technical Details
Message-ID:
<8ube20$hnt$1@news.unizar.es>Path:
arc1-ca.pugleaf.net!unknown!not-for-mailReferences:
<9ks9u8.jc.ln@127.0.0.1>Show Full Headers
Complete Article Headers
X-Google-Language: PORTUGUESE,ASCII
X-Google-Thread: f86c8,8bfdad65296f88d
X-Google-Attributes: gidf86c8,public
From: "J.A. Gutierrez" <spd@daphne.cps.unizar.es>
Subject: Re: Sockets y multiples conexiones.
Date: 2000/11/08
Message-ID: <8ube20$hnt$1@news.unizar.es>
X-Deja-AN: 691159478
Content-Transfer-Encoding: 8bit
References: <9ks9u8.jc.ln@127.0.0.1>
Content-Type: text/plain; charset=ISO-8859-1
X-Complaints-To: usenet@news.unizar.es
X-Trace: news.unizar.es 973683584 18173 155.210.152.20 (8 Nov 2000 11:39:44 GMT)
Organization: Rank
Mime-Version: 1.0
User-Agent: tin/1.4.1-19991201 ("Polish") (UNIX) (IRIX/6.2 (IP22))
NNTP-Posting-Date: 8 Nov 2000 11:39:44 GMT
Newsgroups: es.comp.os.linux.programacion