linux平台IO多路复用 select接口使用例子
生活随笔
收集整理的這篇文章主要介紹了
linux平台IO多路复用 select接口使用例子
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
這幾天在學(xué)習(xí)net-snmp源碼,里面封裝了很多select函數(shù)調(diào)用,這里記錄一下linux上select的用法以及相關(guān)接口。
先看接口:
//頭文件 #include <sys/select.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h>/** 參數(shù)nfds表示監(jiān)聽的描述符個(gè)數(shù),通常等于最大的描述符加一,select最多同時(shí)監(jiān)聽描述符* 數(shù)量有個(gè)上限,FD_SETSIZE(1024),不同平臺(tái)這個(gè)值可能不同,所以如果程序中監(jiān)聽數(shù)量特別* 多的話,建議使用epoll。** 參數(shù) readfds, writefds, exceptfds表示描述符集,可以把我們關(guān)心的描述符放到對(duì)應(yīng)的* 描述符數(shù)組里面,這三個(gè)分別對(duì)應(yīng)著可讀、可寫和異常事件。可以都設(shè)置為NULL,這時(shí)候select* 調(diào)用就相當(dāng)于一個(gè)更精確的sleep。 ** 參數(shù) timeout表示select超時(shí)時(shí)間,如果為NULL的話,表示永久阻塞,除非監(jiān)聽的描述符集上* 有事件發(fā)生或者收到信號(hào),為0的話,表示立即返回,其它的值則表示相應(yīng)的等待時(shí)間。** 成功返回準(zhǔn)備好讀寫的文件描述符數(shù)量,* 返回0表示超時(shí),返回-1表示出錯(cuò)。*/ int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);/* 從fdset中清空該文件描述符標(biāo)志位 */ void FD_CLR(int fd, fd_set *set); /* 判斷該文件描述符上是否有事件發(fā)生 */ int FD_ISSET(int fd, fd_set *set);/* 將該文件描述符添加到fd_set數(shù)組中 */ void FD_SET(int fd, fd_set *set);/* 初始化fdset */ void FD_ZERO(fd_set *set);每次調(diào)用select后,都需要重新清空描述符集并重新添加感興趣的文件描述符。另外,select返回時(shí)會(huì)將 剩余時(shí)間填充到timeout參數(shù)中,因此重新調(diào)用select的時(shí)候也要重新初始化該時(shí)間參數(shù)。示例,創(chuàng)建兩個(gè)udp套接字,使用select循環(huán)監(jiān)聽可讀事件,注意收到事件處理完成后需要重新對(duì)fd_set描述符集進(jìn)行初始化,
這一點(diǎn)不如epoll使用方便。
/*** Description : linux 環(huán)境 select接口使用示例* 創(chuàng)建兩個(gè)udp套接字,然后使用select監(jiān)聽套接字上讀事件。 * Date : 20181001* Author : mason*/#include <sys/time.h> #include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <sys/errno.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <string.h>#define BUFFER_SIZE 512 #define log(fmt, arg...) printf("[udptest] %s:%d "fmt, __FUNCTION__, __LINE__, ##arg)void main() {int sock, sock2;int addr_len, recv_len;char buffer[BUFFER_SIZE] = {0};struct sockaddr_in addr, addr2;fd_set rfds;struct timeval tv;int retval, maxfdp1 = 0;/* 創(chuàng)建UDP套接字 */sock = socket(AF_INET, SOCK_DGRAM, 0);if (sock == -1) {log("create socket fail \r\n");return ;} sock2 = socket(AF_INET, SOCK_DGRAM, 0);if (sock2 == -1) {log("create socket2 fail \r\n");close(sock);return ;} /* 設(shè)置監(jiān)聽地址 */addr.sin_family = AF_INET;addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(40000);addr2.sin_family = AF_INET;addr2.sin_addr.s_addr = INADDR_ANY; addr2.sin_port = htons(30000);addr_len = sizeof(struct sockaddr_in);/* 綁定本地監(jiān)聽地址 */if (0 != bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))){log("bind local listening addr fail,errno : %d \r\n", errno);goto end;} if (0 != bind(sock2, (struct sockaddr *)&addr2, sizeof(struct sockaddr_in))){log("bind local listening addr fail,errno : %d \r\n", errno);goto end;} /* 初始化描述符集 */FD_ZERO(&rfds);/* 添加到描述符集里面 */FD_SET(sock, &rfds);maxfdp1 = maxfdp1 > sock ? (maxfdp1 + 1) : (sock + 1);/* 添加到描述符集里面 */FD_SET(sock2, &rfds);maxfdp1 = maxfdp1 > sock ? (maxfdp1 + 1) : (sock + 1);/* select超時(shí)10s */tv.tv_sec = 10;tv.tv_usec = 0;/* 循環(huán)監(jiān)聽 */for (;;){/* 只監(jiān)聽讀事件 */retval = select(maxfdp1, &rfds, NULL, NULL, &tv);if (retval > 0){/* 判斷是否可讀 */if (FD_ISSET(sock, &rfds)){recv_len = read(sock, buffer, sizeof(buffer));if (recv_len != -1){log("revc from sock : %s\r\n", buffer);memset(buffer, 0, sizeof(buffer));}}if (FD_ISSET(sock2, &rfds)){recv_len = read(sock2, buffer, sizeof(buffer));if (recv_len != -1){log("revc from sock2 : %s\r\n", buffer);memset(buffer, 0, sizeof(buffer));}}}else if (retval == 0){/* select 超時(shí) */log("select timeout \r\n");}else{log("select error \r\n");}/* 清空標(biāo)志位 */FD_ZERO(&rfds);/* 重新設(shè)置超時(shí) */tv.tv_sec = 5;/* 重新添加到select監(jiān)聽數(shù)組中 */FD_SET(sock, &rfds);FD_SET(sock2, &rfds);}end:close(sock);close(sock2);return; }Makefile:
# # Linux 同步IO復(fù)用 select接口例子 #app:gcc -o select_demo select_demo.cclean:rm -rf *.o select_demo運(yùn)行截圖:
參考資料:
1. man select?http://www.man7.org/linux/man-pages/man2/select.2.html
2. 《UNIX網(wǎng)絡(luò)編程卷一 套接字API》第6章 IO多路復(fù)用
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的linux平台IO多路复用 select接口使用例子的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 固收类理财产品简单介绍 虽然收益不高但是
- 下一篇: Linux开发环境搭建三 使用mount