🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: es.comp.os.linux.programacion
Article #14480

Re: Sockets y multiples conexiones.

#14480
From: J.A. Gutierrez
Date: Wed, 08 Nov 2000 00:00
493 lines
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-mail
References: <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