Simplest Socket socket programming (2)-Poll () and epoll ()

Source: Internet
Author: User
Tags htons
Simplest Socket socket programming (2)-Poll () and epoll ()

Author: gaopenghigh. For more information, see the source. (Original address)

This document describes how to usepoll()Andepoll()The main step of Socket network programming in UNIX environment is to implement a simple server and client code instance and a network service, which accepts a string command, execute the command and return the result to the client.

For the basic concepts of Socket network programming and the Principles and Examples of multi-process and multi-thread network servers, refer to the simplest Socket socket programming.

Aboutpoll()Andepoll()For more information, see step-by-step understanding of Linux I/O (2)-advanced I/O

Client
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#define BUFLEN 256void error(const char *msg){    perror(msg);    exit(0);}int main(int argc, char *argv[]){    int sockfd, portno, n;    struct sockaddr_in serv_addr;    struct hostent *server;    char buffer[BUFLEN];    if (argc < 3) {       fprintf(stderr,"usage %s hostname port\n", argv[0]);       exit(0);    }    portno = atoi(argv[2]);    if ((server = gethostbyname(argv[1])) == NULL) {        fprintf(stderr,"ERROR, no such host\n");        exit(0);    }    bzero((char *) &serv_addr, sizeof(serv_addr));    serv_addr.sin_family = AF_INET;    bcopy((char *)server->h_addr,          (char *)&serv_addr.sin_addr.s_addr,          server->h_length);    serv_addr.sin_port = htons(portno);    while (1) {        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)            error("ERROR opening socket");        if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)            error("ERROR connecting");        printf(">>> ");        bzero(buffer, BUFLEN);        fgets(buffer, BUFLEN, stdin);        if((n = send(sockfd, buffer, strlen(buffer), 0)) <= 0)             error("ERROR writing to socket");        bzero(buffer, BUFLEN);        while ((n = recv(sockfd, buffer, BUFLEN, 0)) > 0) {            printf("%s",buffer);        }    }    return 0;}
Server implemented by poll ()
/* A simple server to run system commands use poll */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <poll.h>#include <fcntl.h>#define PORTNO 4444#define BACKLOG 10#define BUFLEN 256#define MAXCONN 100#define TRUE 1#define FALSE 0void error(const char *msg) {    perror(msg);}/* * function really do the service * run cmd geted from client and return the output to client */void serve(struct pollfd *pfd) {    int n;    char buffer[BUFLEN];    FILE *fp;    bzero(buffer, BUFLEN);    printf("in serve ,fd=%d\n", pfd->fd);    if (pfd->revents & POLLIN) {                /* read */        if ((n = read(pfd->fd, buffer, BUFLEN)) < 0)            printf("ERROR reading from socket : %d", n);        printf("CMD : %s\n",buffer);        if ((fp = popen(buffer, "r")) == NULL)            error("ERROR when popen");        while (fgets(buffer, BUFLEN, fp) != NULL) {            if (send(pfd->fd, buffer, BUFLEN, 0) == -1)                error("send ERROR");        }        printf("serve end, closing %d\n", pfd->fd);        close(pfd->fd);        pfd->fd = -1;        pclose(fp);    }}/* * Init listen socket and bind it to addr, return the listen socket */int init_server() {    int sockfd;    struct sockaddr_in serv_addr;    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {        error("ERROR opening socket");        exit(1);    }    bzero((char *) &serv_addr, sizeof(serv_addr));    serv_addr.sin_family = AF_INET;    serv_addr.sin_addr.s_addr = INADDR_ANY;    serv_addr.sin_port = htons(PORTNO);    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {        error("ERROR on binding");        exit(1);    }    return sockfd;}/* * set fd nonblocking, success return 0, fail return -1 */int setnonblocking(int fd) {    if (fd > 0) {        int flags = fcntl(fd, F_GETFL, 0);        flags = flags|O_NONBLOCK;        if (fcntl(fd, F_SETFL, flags) == 0) {            printf("setnonblocking success!\n");            return 0;        }    }    return -1;}void printfd(struct pollfd array[], int n) {    int i;    printf("array = ");    for(i = 0; i < n; i++)        printf("[%d]:%d ", i, array[i].fd);    printf("\n");}/* * Use poll() to serve for every connection */int main(int argc, char *argv[]) {    int endserver = FALSE;    int listen_sock, conn_sock, pos, i, j;    struct sockaddr_in cli_addr;    socklen_t clilen = sizeof(cli_addr);    /* INIT pollfd structures */    struct pollfd allfds[MAXCONN];    printf("sizeof(allfds)=%d\n", (int)sizeof(allfds));    memset(allfds, 0, sizeof(allfds));    int nfds = 0;    /* number of fds in allfds */    int currentsize; /* current size of allfds */    int poll_result;    /* init listen socket, bind, listen */    listen_sock = init_server();    setnonblocking(listen_sock);    listen(listen_sock, BACKLOG);    /* add listen_socket to allfds array */    allfds[0].fd = listen_sock;    allfds[0].events = POLLIN;    nfds++;    while (endserver == FALSE) {        printfd(allfds, nfds);        printf("nfds=%d\n", nfds);        /* wait for events on sockets, timeout = -1 means waite forever */        poll_result = poll(allfds, nfds, -1);        if (poll_result == -1) {            error("poll ERROR");            break;        } else if (poll_result == 0) {            printf("poll round timeout, enther another poll...\n");            continue;        }        /*******************************************************************/        /* One or more descriptors are readable                            */        /*******************************************************************/        currentsize = nfds;        printf("correntsize=%d\n", currentsize);        for (pos = 0; pos < currentsize; pos++) {            if (allfds[pos].revents & POLLIN &&                    allfds[pos].fd == listen_sock) {  /* listen socket */                printf("event on listen sock\n");                /* Accept all incomming connections */                do {                    printf("listen_sock=%d\n", listen_sock);                    conn_sock = accept(listen_sock,                                   (struct sockaddr *)&cli_addr, &clilen);                    if (conn_sock < 0)                        continue;                    setnonblocking(conn_sock);                    if (nfds >= MAXCONN) {                        error("nfds >= MAXCONN");                        break;                    }                    allfds[nfds].fd = conn_sock;                    allfds[nfds].events = POLLIN;                    nfds++;                } while(conn_sock != -1);            /* regular socket */            } else {                serve(&allfds[pos]);            }            /* comparess allfds, delete the items which fd = -1 */            for (i = 0; i < nfds; i++) {                if (allfds[i].fd == -1) {                    for (j = i; j < nfds; j++) {                        allfds[j] = allfds[j+1];                    }                    nfds--;                    i--;                }            }        }    }    /* end server */    for (i = 0; i < nfds; i++) {        if (allfds[i].fd >= 0)            close(allfds[i].fd);    }    return 0;}
Server implemented by epoll ()
/* A simple server to run system commands use poll */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/epoll.h>#include <fcntl.h>#define PORTNO 4444#define BACKLOG 10#define BUFLEN 256#define MAXCONN 100#define TRUE 1#define FALSE 0void error(const char *msg) {    perror(msg);}/* * function really do the service * run cmd geted from client and return the output to client */void serve(int fd) {    int n;    char buffer[BUFLEN];    FILE *fp;    bzero(buffer, BUFLEN);    printf("in serve ,fd=%d\n", fd);    if ((n = read(fd, buffer, BUFLEN)) < 0)        printf("ERROR reading from socket : %d", n);    printf("CMD : %s\n",buffer);    if ((fp = popen(buffer, "r")) == NULL)        error("ERROR when popen");    while (fgets(buffer, BUFLEN, fp) != NULL) {        if (send(fd, buffer, BUFLEN, 0) == -1)            error("send ERROR");    }    printf("serve end, closing %d\n", fd);    pclose(fp);}/* * Init listen socket and bind it to addr, return the listen socket */int init_server() {    int sockfd;    struct sockaddr_in serv_addr;    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {        error("ERROR opening socket");        exit(1);    }    bzero((char *) &serv_addr, sizeof(serv_addr));    serv_addr.sin_family = AF_INET;    serv_addr.sin_addr.s_addr = INADDR_ANY;    serv_addr.sin_port = htons(PORTNO);    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {        error("ERROR on binding");        exit(1);    }    return sockfd;}/* * set fd nonblocking, success return 0, fail return -1 */int setnonblocking(int fd) {    if (fd > 0) {        int flags = fcntl(fd, F_GETFL, 0);        flags = flags|O_NONBLOCK;        if (fcntl(fd, F_SETFL, flags) == 0) {            printf("setnonblocking success!\n");            return 0;        }    }    return -1;}/* * Use poll() to serve for every connection */int main(int argc, char *argv[]) {    int endserver = FALSE;    int listen_sock, conn_sock, n;    struct sockaddr_in cli_addr;    socklen_t clilen = sizeof(cli_addr);    /* INIT pollfd structures */    struct epoll_event ev, events[MAXCONN];    int nfds;    int epollfd = epoll_create(10);    if (epollfd == -1) {        printf("epoll_create error\n");        exit(1);    }    /* init listen socket, bind, listen */    listen_sock = init_server();    setnonblocking(listen_sock);    listen(listen_sock, BACKLOG);    /* register listen_sock to epollfd */    ev.events = EPOLLIN;    ev.data.fd = listen_sock;    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) {        printf("ERROR: epoll_ctl\n");        exit(1);    }    while (endserver == FALSE) {        nfds = epoll_wait(epollfd, events, MAXCONN, -1);        if (nfds == -1) {            printf("epoll_wait ERROR\n");            exit(1);        }        for (n = 0; n < nfds; n++) {            if (events[n].data.fd == listen_sock) { /* listen socket */                do {                    printf("listen_sock=%d\n", listen_sock);                    conn_sock = accept(listen_sock,                                   (struct sockaddr *)&cli_addr, &clilen);                    if (conn_sock < 0)                        continue;                    setnonblocking(conn_sock);                    ev.events = EPOLLIN|EPOLLET;                    ev.data.fd = conn_sock;                    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &ev)                            == -1) {                        printf("epoll_ctl for conn_sock ERROR\n");                        exit(1);                    }                } while(conn_sock != -1);            } else { /* regular connection */                serve(events[n].data.fd);                ev.events = EPOLLIN|EPOLLET;                ev.data.fd = conn_sock;                if (epoll_ctl(epollfd, EPOLL_CTL_DEL, events[n].data.fd, &ev)                        == -1) {                    printf("epoll_ctl DEL ERROR\n");                    exit(1);                }                close(events[n].data.fd);            }        }    }    return 0;}

References:

  • Advanced Programming in UNIX environment
  • Using poll () instead of select ()
  • Man pages

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.