⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rpnsrv2.c

📁 目前已经有很多介绍计算机网络的书籍
💻 C
字号:
/* rpnsrv2.c: *  * Example RPN Server * using select(2) : */#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <time.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/wait.h>#include <gmp.h>#ifndef SHUT_RDWR#define SHUT_RDWR 3#endifextern int mkaddr(void *addr,    int *addr_len,    char *input_address,    char *protocol);extern void rpn_process(FILE *tx,    char *buf);extern void rpn_free(mpz_t **v);#define MAX_STACK       32#define MAX_CLIENTS     64/* * Declared in rpneng2.c : */extern mpz_t **stack;extern int sp;/* * Client context Info: */typedef struct {    mpz_t   **stack;  /* Stack Array */    int     sp;         /* Stack ptr */    FILE    *rx;        /* Recv FILE */    FILE    *tx;        /* Xmit FILE */} ClientInfo;ClientInfo client[MAX_CLIENTS];/* * This function reports the error and * exits back to the shell : */static voidbail(const char *on_what) {    if ( errno != 0 ) {        fputs(strerror(errno),stderr);        fputs(": ",stderr);    }    fputs(on_what,stderr);    fputc('\n',stderr);    exit(1);}/* * Process client c : */static intprocess_client(int c) {    char buf[4096];          /* I/O Buffer */    FILE *rx = client[c].rx;    FILE *tx = client[c].tx;    /*     * Install correct RPN stack :     */    stack = client[c].stack;    sp = client[c].sp;    /*     * If not EOF, process one line :     */    if ( !feof(rx)      && fgets(buf,sizeof buf,rx) )        rpn_process(tx,buf);    if ( !feof(rx) ) {        /* Save SP and exit */        client[c].sp = sp;        return 0;    }    /*     * Close this client's connection:     */    fclose(tx);    shutdown(fileno(rx),SHUT_RDWR);    fclose(rx);    client[c].rx = client[c].tx = NULL;    while ( sp > 0 )        rpn_free(&stack[--sp]);    free(stack);    client[c].stack = NULL;    client[c].sp = 0;    return EOF;}/* * Main program : */intmain(int argc,char **argv) {    int z;    char *srvr_addr = "127.0.0.1:9090";    struct sockaddr_in adr_srvr;/* AF_INET */    struct sockaddr_in adr_clnt;/* AF_INET */    int len_inet;               /* length  */    int s = -1;                  /* Socket */    int c = -1;           /* Client socket */    int n;    /* return val from select(2) */    int mx;                  /* Max fd + 1 */    fd_set rx_set;             /* Read set */    fd_set wk_set;          /* Working set */    struct timeval tv;    /* Timeout value */    /*     * Initialize client structure:     */    for ( z=0; z<MAX_CLIENTS; ++z ) {        client[z].stack = NULL;        client[z].sp = 0;        client[z].rx = NULL;        client[z].tx = NULL;    }    /*     * Use a server address from the command     * line, otherwise default to 127.0.0.1:     */    if ( argc >= 2 )        srvr_addr = argv[1];    len_inet = sizeof adr_srvr;    z = mkaddr(&adr_srvr,&len_inet,        srvr_addr,"tcp");    if ( z < 0 || !adr_srvr.sin_port ) {        fprintf(stderr,"Invalid server "            "address, or no port number "            "was specified.\n");        exit(1);    }    /*     * Create a TDP/IP socket to use :     */    s = socket(PF_INET,SOCK_STREAM,0);    if ( s == -1 )        bail("socket(2)");    /*     * Bind the server address:     */    z = bind(s,(struct sockaddr *)&adr_srvr,            len_inet);    if ( z == -1 )        bail("bind(2)");    /*     * Make it a listening socket:     */    z = listen(s,10);    if ( z == -1 )        bail("listen(2)");    /*     * Express interest in socket     * s for read events :     */    FD_ZERO(&rx_set);   /* Init. */    FD_SET(s,&rx_set);    /* + s */    mx = s + 1;    /* max fd + 1 */    /*     * Start the server loop :     */    for (;;) {        /*         * Copy the rx_set to wk_set :         */        FD_ZERO(&wk_set);        for ( z=0; z<mx; ++z ) {            if ( FD_ISSET(z,&rx_set) )                FD_SET(z,&wk_set);        }        /*         * Sample timeout of 2.03 secs         */        tv.tv_sec = 2;        tv.tv_usec = 30000;        n = select(mx,&wk_set,NULL,NULL,&tv);        if ( n == -1 ) {            fprintf(stderr,"%s: select(2)\n",                strerror(errno));            exit(1);        } else if ( !n ) {            /* puts("Timeout."); */            continue;        }        /*         * Check if a connect has occured:         */        if ( FD_ISSET(s,&wk_set) ) {            /*             * Wait for a connect :             */            len_inet = sizeof adr_clnt;            c = accept(s,                (struct sockaddr *)&adr_clnt,                &len_inet);            if ( c == -1 )                bail("accept(2)");            /*             * See if we've exceeded server             * capacity. If so, close the             * socket and wait for the             * next event :             */            if ( c >= MAX_CLIENTS ) {                close(c);   /* At capacity */                continue;            }            /*             * Create streams :             */            client[c].rx = fdopen(c,"r");            if ( !client[c].rx ) {                close(c);  /* Failed */                continue;            }            client[c].tx = fdopen(dup(c),"w");            if ( !client[c].tx ) {                fclose(client[c].rx);                continue;            }            if ( c + 1 > mx )                mx = c + 1;            /*             * Set both streams to line             * buffered mode :             */            setlinebuf(client[c].rx);            setlinebuf(client[c].tx);            /*             * Allocate a stack :             */            client[c].sp = 0;            client[c].stack =                (mpz_t **) malloc(                    sizeof (mpz_t *)                    * MAX_STACK);            FD_SET(c,&rx_set);        }         /*         * Check for client activity :         */        for ( c=0; c<mx; ++c ) {            if ( c == s )                continue;   /* Not s */            if ( FD_ISSET(c,&wk_set) ) {                if ( process_client(c) == EOF ) {                    FD_CLR(c,&rx_set);                }            }        }        /*         * Reduce mx if we are able to :         */        for ( c = mx - 1;              c >= 0 && !FD_ISSET(c,&rx_set);              c = mx - 1 )                mx = c;    }    /* Control never gets here */    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -