国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 操作系統(tǒng) > 正文

IO復(fù)用_select函數(shù)

2024-06-28 13:19:54
字體:
供稿:網(wǎng)友
IO復(fù)用_select函數(shù)

select函數(shù):

#include <sys/select.h>#include <time.h>#include <sys/types.h>#include <unistd.h>int select(int nfds,               fd_set*readfds,               fd_set*writefds,               fd_set*exceptfds,               struct timeval*timeout);

參數(shù)含義:

  • nfds:一個整型變量,它比所有文件描述符集合中的文件描述符的最大值大1。使用select的時(shí)候,必須計(jì)算最大值的文件描述符的值,將值通過nfds傳入。
  • readfds:這個文件描述符集合監(jiān)視文件集中的任何文件是否有數(shù)據(jù)可讀,當(dāng)select()返回的時(shí)候,readfds將清除其中不可讀的文件描述符,只留下可讀的文件描述符,即可以被recv()、read()等進(jìn)行讀操作。
  • writefds:這個文件描述符集合監(jiān)視文件集中的任何文件是否有數(shù)據(jù)可寫,當(dāng)select()返回的時(shí)候,readfds將清除其中不可寫的文件描述符,只留下可寫的文件描述符,即可以被send()、write()等進(jìn)行讀操作。
  • exceptfds:這個文件集合將監(jiān)視文件中的任何文件是否發(fā)生錯誤,其實(shí),它還能用于監(jiān)視帶外數(shù)據(jù)OOB,帶外數(shù)據(jù)使用MSG_OOB標(biāo)志發(fā)送到套接字上。當(dāng)select()返回時(shí),readfds將清除其中的其他文件描述符,只留下可讀的OOB數(shù)據(jù)。
  • timeout:設(shè)置在select()所監(jiān)視的文件集合中的事件沒有發(fā)生時(shí),最長的等待時(shí)間,當(dāng)超過這個時(shí)間時(shí),函數(shù)返回。當(dāng)超時(shí)返回為NULL時(shí),表示阻塞操作,會一直等待,直到某個監(jiān)視的文件集中的某個文件描述符符合返回條件。當(dāng)timeout的值為0時(shí),select()會立即返回。
  • sigmask:信號

返回值:

當(dāng)返回大于0的正值:監(jiān)視的文件集合中的文件描述符符合上述要求。

當(dāng)?shù)扔?時(shí):超時(shí)。

當(dāng)為-1時(shí):發(fā)生錯誤

struct timeval結(jié)構(gòu):

struct timeval{       time_t tv_sec;                //秒       long tv_usec;                 // 微秒,即1/1000000s}

另外,還有4個宏操作文件描述符的集合:

FD_ZERO():清理文件描述符集合;

FD_SET():向某個文件描述符集合中加入文件描述符;

FD_CLR():從某個文件描述符集合中取某個文件描述符;

FD_ISSET():測試某個文件描述符是否為某個集合中的一員。

注:文件描述符的集合存在最大的限制,其最大值為FD_SETSIZE,當(dāng)超出最大值時(shí),發(fā)生不可預(yù)料的事。同時(shí),可以修改這個值,但是監(jiān)視集合的效率會降低,是因?yàn)閟elect()輪詢是線性的。在這里,有個更加牛B的的函數(shù),請查看epoll:epoll沒有最大并發(fā)連接的限制,上限是最大可以打開文件的數(shù)目,這個數(shù)字一般遠(yuǎn)大于2048, 一般來說這個數(shù)目和系統(tǒng)內(nèi)存關(guān)系很大。最大的優(yōu)點(diǎn)就在于它只管你“活躍”的連接,而跟連接總數(shù)無關(guān),因此在實(shí)際的網(wǎng)絡(luò)環(huán)境中,epoll的效率就會遠(yuǎn)遠(yuǎn)高于select和poll。在內(nèi)存拷貝上,epoll在這點(diǎn)上使用了“共享內(nèi)存”,這個內(nèi)存拷貝也省略了。

附加:使用select()寫的IO復(fù)用循環(huán)服務(wù)器模型的例子

  1 #include <sys/types.h>  2 #include <sys/socket.h>  3 #include <netinet/in.h>  4 #include <time.h>  5 #include <string.h>  6 #include <stdio.h>  7 #include <pthread.h>  8  #include <sys/select.h>  9 #define BUFFLEN 1024 10 #define SERVER_PORT 8888 11 #define BACKLOG 5 12 #define CLIENTNUM 1024/*最大支持客戶端數(shù)量*/ 13  14 /*可連接客戶端的文件描述符數(shù)組*/ 15 int connect_host[CLIENTNUM]; 16 int connect_number =  0; 17  18 //處理客戶端請求函數(shù) 19 static void *handle_request(void *argv) 20 {     21     time_t now;        /*時(shí)間*/ 22     char buff[BUFFLEN];/*收發(fā)數(shù)據(jù)緩沖區(qū)*/ 23     int n = 0; 24      25     int maxfd = -1;/*最大偵聽文件描述符*/ 26     fd_set scanfd;    /*偵聽描述符集合*/ 27     struct   timeval   timeout;     /*超時(shí)*/ 28     timeout.tv_sec     =   1; /*   阻塞1秒后超時(shí)返回   */      29     timeout.tv_usec   =   0;      30      31     int i = 0; 32     int err  = -1; 33     for(;;) 34     {    35         /*最大文件描述符值初始化為-1*/         36         maxfd = -1; 37         FD_ZERO(&scanfd);/*清零文件描述符集合*/ 38         for(i=0;i<CLIENTNUM;i++)/*將文件描述符放入集合*/ 39         { 40             if(connect_host[i] != -1)/*合法的文件描述符*/ 41             { 42                 FD_SET(connect_host[i], &scanfd);/*放入集合*/ 43                 if(maxfd <     connect_host[i])/*更新最大文件描述符值*/ 44                 { 45                     maxfd = connect_host[i]; 46                 } 47             } 48         } 49         /*select等待*/ 50         err = select(maxfd + 1, &scanfd, NULL, NULL, &timeout) ;         51         switch(err) 52         { 53             case 0:/*超時(shí)*/ 54                 break; 55             case -1:/*錯誤發(fā)生*/ 56                 break; 57             default:/*有可讀套接字文件描述符*/ 58                 if(connect_number<=0) 59                     break; 60                 for(i = 0;i<CLIENTNUM;i++) 61                 { 62                     /*查找激活的文件描述符*/ 63                     if(connect_host[i] != -1) 64                     if(FD_ISSET(connect_host[i],&scanfd))    65                     {   66                         memset(buff, 0, BUFFLEN);/*清零*/ 67                         n = recv(connect_host[i], buff, BUFFLEN,0);/*接收發(fā)送方數(shù)據(jù)*/ 68                         if(n > 0 && !strncmp(buff, "TIME", 4))/*判斷是否合法接收數(shù)據(jù)*/ 69                         { 70                             memset(buff, 0, BUFFLEN);/*清零*/ 71                             now = time(NULL);/*當(dāng)前時(shí)間*/ 72                             sPRintf(buff, "%24s/r/n",ctime(&now));/*將時(shí)間拷貝入緩沖區(qū)*/ 73                             send(connect_host[i], buff, strlen(buff),0);/*發(fā)送數(shù)據(jù)*/ 74                         } 75                         /*更新文件描述符在數(shù)組中的值*/ 76                         connect_host[i] = -1; 77                         connect_number --;    /*客戶端計(jì)數(shù)器減1*/     78                         /*關(guān)閉客戶端*/ 79                         close(connect_host[i]);                             80                     }  81                 } 82                 break;      83         }           84     }  85      86     return NULL; 87 } 88  89 //處理客戶端連接函數(shù) 90 static void *handle_connect(void *argv) 91 {     92     int s_s = *((int*)argv) ;/*獲得服務(wù)器偵聽套接字文件描述符*/ 93     int s_c = -1;/*連接客戶端文件描述符*/ 94     struct sockaddr_in from; 95     int len = sizeof(from); 96     /*接收客戶端連接*/ 97     for(;;) 98     { 99         int i = 0;100         int s_c = accept(s_s, (struct sockaddr*)&from, &len);/*接收客戶端的請求*/101         printf("a client connect, from:%s/n",inet_ntoa(from.sin_addr));102         /*查找合適位置,將客戶端的文件描述符放入*/                103         for(i=0;i<CLIENTNUM;i++)104         {105             if(connect_host[i] == -1)/*找到*/106             {107                 /*放入*/108                 connect_host[i]= s_c;109                 110                 /*客戶端計(jì)數(shù)器加1*/111                 connect_number ++;112                 /*繼續(xù)輪詢等待客戶端連接*/113                 break;                        114             }    115         }        116     }    117     return NULL;118 }119 120 int main(int argc, char *argv[])121 {122     int s_s;    /*服務(wù)器套接字文件描述符*/123     struct sockaddr_in local;    /*本地地址*/    124     int i = 0;125     memset(connect_host, -1, CLIENTNUM);126     127     /*建立TCP套接字*/128     s_s = socket(AF_INET, SOCK_STREAM, 0);129     130     /*初始化地址接哦股*/131     memset(&local, 0, sizeof(local));/*清零*/132     local.sin_family = AF_INET;/*AF_INET協(xié)議族*/133     local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/134     local.sin_port = htons(SERVER_PORT);/*服務(wù)器端口*/135     136     /*將套接字文件描述符綁定到本地地址和端口*/137     int err = bind(s_s, (struct sockaddr*)&local, sizeof(local));138     err = listen(s_s, BACKLOG);/*偵聽*/139     140     pthread_t  thread_do[2];/*線程ID*/141     /*創(chuàng)建線程處理客戶端連接*/142     pthread_create(&thread_do[0],/*線程ID*/143                     NULL,/*屬性*/144                     handle_connect,/*線程回調(diào)函數(shù)*/145                     (void*)&s_s);        /*線程參數(shù)*/146     /*創(chuàng)建線程處理客戶端請求*/                    147     pthread_create(&thread_do[1],/*線程ID*/148                     NULL,/*屬性*/149                     handle_request,/*線程回調(diào)函數(shù)*/150                     NULL);        /*線程參數(shù)*/151     /*等待線程結(jié)束*/152     for(i=0;i<2;i++)153         pthread_join(thread_do[i], NULL);154     155     close(s_s);156     157     return 0;        158 }

作者:orange1438出處:http://www.CUOXin.com/orange1438/本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 金堂县| 区。| 五河县| 崇州市| 湖口县| 二手房| 湘乡市| 荆州市| 东方市| 栾川县| 开化县| 北碚区| 德安县| 桃江县| 台东市| 封丘县| 江川县| 邯郸县| 汾西县| 舞钢市| 南召县| 桂平市| 晴隆县| 简阳市| 北碚区| 浦江县| 临汾市| 遂宁市| 麟游县| 黑水县| 芒康县| 安义县| 昌江| 许昌县| 九寨沟县| 邹平县| 百色市| 西华县| 马鞍山市| 临海市| 边坝县|