高效能網路編程 - select系統調用

來源:互聯網
上載者:User

標籤:select   fd_set   msg_oob   


     IO複用使得程式能夠同時監聽多個檔案描述符,比如用戶端需要同時處理使用者輸入和網路連接,伺服器端需要同時處理監聽通訊端和串連通訊端,select系統調用可以使得我們監聽自己感興趣描述符,可讀,可寫,異常等事件。select能處理的異常只有帶外資料。能同時處理描述符的數量受限於FD_SETSIZE的大小(一般1024)。下面這個程式展示了它的一般用法。
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <libgen.h> //basename#include <arpa/inet.h>#include <sys/types.h>#include <sys/socket.h>#include <assert.h>#include <errno.h>int main(int argc, char *argv[]){    int i, maxi;    char buf[1024];    fd_set read_fds, all_read_fds;    fd_set exception_fds, all_exception_fds;    int nready, connectfd[FD_SETSIZE];      int connfd,sockfd,maxfd;        struct sockaddr_in client_address;    socklen_t client_addrlen = sizeof(client_address);        if(argc <= 2){         printf("usage: %s ip_address port_number\n", basename(argv[0]));        return 1;    }       const char *ip = argv[1];    int port = atoi(argv[2]);        int ret = 0;    struct sockaddr_in address;    bzero(&address, sizeof(address));    address.sin_family = AF_INET;    inet_pton(AF_INET, ip, &address.sin_addr);    address.sin_port = htons(port);    int listenfd = socket(AF_INET, SOCK_STREAM, 0);    assert(listenfd >= 0);    ret = bind(listenfd, (struct sockaddr *)&address, sizeof(address));    assert(ret != -1);    ret = listen(listenfd, 5);    assert(ret != -1);    maxfd = listenfd;    maxi = -1;    for(i= 0; i < FD_SETSIZE; i++)        connectfd[i] = -1;    FD_ZERO(&all_read_fds);    FD_ZERO(&all_exception_fds);    FD_SET(listenfd, &all_read_fds);    //do not care about the OOB of listen socket    while(1){        read_fds = all_read_fds;        exception_fds = all_exception_fds;        memset(buf, 0, sizeof(buf));        nready = select(maxfd + 1, &read_fds, NULL, &exception_fds, NULL);        //new client connection coming        if(FD_ISSET(listenfd, &read_fds)){            connfd = accept(listenfd, (struct sockaddr *)&client_address, &client_addrlen);            if(connfd < 0){                perror("accept failed\n");                exit(-1);            }            for(i=0; i < FD_SETSIZE; i++)                if(connectfd[i] < 0){                    connectfd[i] = connfd;                    break;                }            if( i == FD_SETSIZE){                printf("too many clients..\n");                exit(-1);            }            // add new descriptor to the read set and exception set            FD_SET(connfd, &all_read_fds);            FD_SET(connfd, &all_exception_fds);            if(connfd > maxfd)                maxfd = connfd;            if(i > maxi)                maxi = i;// update the max index in connectfd[]            //we complete the listen socktet processing            if(--nready <= 0)                continue;        }        for(i = 0; i <= maxi; i++){            //check all the connected clients for data            if((sockfd = connectfd[i]) < 0)                continue;            if(FD_ISSET(sockfd, &read_fds)){                ret = recv(sockfd, buf, sizeof(buf) - 1, 0);                if(ret <= 0)                    break;//connection closed                // process logic                printf("get %d bytes of normal data:%s\n", ret, buf);            //we complete the listen socktet processing            if(--nready <= 0)                continue;        }        for(i = 0; i <= maxi; i++){            //check all the connected clients for data            if((sockfd = connectfd[i]) < 0)                continue;            if(FD_ISSET(sockfd, &read_fds)){                ret = recv(sockfd, buf, sizeof(buf) - 1, 0);                if(ret <= 0)                    break;//connection closed                // process logic                printf("get %d bytes of normal data:%s\n", ret, buf);            }else if(FD_ISSET(sockfd, &exception_fds)){                //handle exceptions                //get out of band data                 ret = recv(connfd, buf, sizeof(buf) - 1, MSG_OOB);                if(ret <= 0)                    break;                printf("get %d bytes of OOB data: %s", ret, buf);            }            FD_CLR(sockfd, &all_read_fds);            FD_CLR(sockfd, &all_exception_fds);            //after we deal with this client            close(sockfd);            if(--nready <= 0)                break;        }    }    close(listenfd);    return 0;}



參考:《高效能伺服器編程》和《UNP》


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.