APUE Learning Example Source Code
guowenxue
2020-04-30 b0053f87034ff358b7ccadc7f2d9643e9a7767e7
prj1_tlv/tlv_server.c
@@ -19,10 +19,15 @@
#include "logger.h"
#include "proc.h"
#include "socket.h"
#define PROG_VERSION     "1.0.0"
#define DEF_LOG_FILE     "tlv_server.log"
#define DEF_LISTEN_IP    "0.0.0.0"
#define DEF_LISTEN_PORT  10086
#define MAX_EVENTS       512
static void banner(void)
{
@@ -52,8 +57,9 @@
    int                   opt; 
    int                   i = 0; 
    //int                   rv = 0;
    int                   rv = 0;
    int                   debug = 0;
    int                   port = DEF_LISTEN_PORT;
    char                  pid_file[64] = { 0 }; /* The file used to record the PID */
    const char           *progname=NULL;
@@ -62,7 +68,15 @@
    char                 *log_file = DEF_LOG_FILE;
    logger_t              logger;
    socket_t              sock;
    int                   epollfd;
    int                   connfd;
    struct epoll_event    event_array[MAX_EVENTS];
    char                  buf[1024];
    struct option long_options[] = { 
        {"port", required_argument, NULL, 'p'},
        {"debug", no_argument, NULL, 'd'}, 
        {"level", required_argument, NULL, 'l'}, 
        {"version", no_argument, NULL, 'v'}, 
@@ -71,14 +85,18 @@
    };
    memset(&logger, 0, sizeof(logger));
    memset(&sock, 0, sizeof(sock));
    progname = basename(argv[0]); /* get program name */
    /* parser the command line parameters */ 
    while ((opt = getopt_long(argc, argv, "c:dl:vh", long_options, NULL)) != -1)
    while ((opt = getopt_long(argc, argv, "p:dl:vh", long_options, NULL)) != -1)
    { 
        switch (opt) 
        {
            case 'p': /* listen port  */
                port = atoi(optarg);
                break;
            case 'd': /* set debug running */
                debug = 1;
@@ -105,6 +123,12 @@
        } 
    }
    if( port <= 0 )
    {
        printf("ERROR: no listen port specified, refer to program usage\n\n");
        program_usage(progname);
    }
    /* check program already running or not, if already running then exit, or set running as daemon */
    snprintf(pid_file, sizeof(pid_file), "/var/run/%s.pid", progname);
    if( !debug )
@@ -114,6 +138,8 @@
            printf("Programe already running, exit now.\n");
            return -1;
        }
        set_daemon_running(pid_file);
    }
    /* initial and open logger system */
@@ -126,13 +152,92 @@
    /* install signal proc handler */
    install_proc_signal();
    log_nrml("Program start running\n");
    log_nrml("TLV server program start running\n");
    set_socket_rlimit();
    if( socket_listen(&sock, DEF_LISTEN_IP, port) < 0 )
    {
        log_err("create listen socket failure\n");
        return -2;
    }
    if( (epollfd=epoll_init(MAX_EVENTS, sock.fd)) < 0 )
    {
        log_err("initial epoll for listen socket failure\n");
        return -2;
    }
    /* g_signal.stop defined in proc.c, and will be set when catch stop signal */
    while( !g_signal.stop )
    {
        log_dbg("Program still running\n");
        sleep(3);
        /* program will blocked here */
        rv = epoll_wait(epollfd, event_array, MAX_EVENTS, -1/* never timeout */);
        if( rv < 0 )
        {
            log_err("epoll failure: %s\n", strerror(errno));
            continue;
        }
        else if( rv == 0)
        {
            log_err("epoll get timeout\n");
            continue;
        }
        /* rv>0 is the active events count */
        for(i=0; i<rv; i++)
        {
            if ( (event_array[i].events&EPOLLERR) || (event_array[i].events&EPOLLHUP) )
            {
                log_err("epoll_wait get error on fd[%d]: %s\n", event_array[i].data.fd, strerror(errno));
                epoll_del(epollfd, event_array[i].data.fd);
                close(event_array[i].data.fd);
            }
            /* listen socket get event means new client start connect now */
            if( event_array[i].data.fd == sock.fd )
            {
                struct epoll_event       event;
                if( (connfd=accept(sock.fd, (struct sockaddr *)NULL, NULL)) < 0)
                {
                    log_nrml("accept new client failure: %s\n", strerror(errno));
                    continue;
                }
                log_info("accept new client socket[%d]\n", connfd);
                event.data.fd = connfd;
                event.events =  EPOLLIN;
                epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd, &event);
#if 0
                if( epoll_add(epollfd, connfd) < 0 )
                {
                    close(connfd);
                    log_err("epoll add client socket failure, rv=%d\n", rv);
                }
                log_dbg("epoll add new client socket[%d] ok.\n", connfd);
#endif
            }
            else
            {
                rv=read(event_array[i].data.fd, buf, sizeof(buf));
                if( rv <= 0 )
                {
                    printf("socket[%d] read failure [%s] or disconncet, close and remove now.\n",
                            event_array[i].data.fd, strerror(errno));
                    epoll_del(epollfd, event_array[i].data.fd);
                    close( event_array[i].data.fd );
                    continue;
                }
                else
                {
                    log_dbg("socket[%d] receive %d bytes data\n", event_array[i].data.fd, rv);
                    logger_dump(LOG_LEVEL_INFO, buf, rv);
                }
            }
        }
    }
    logger_term();