日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

I/O复用函数的使用——poll

發(fā)布時間:2024/4/17 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 I/O复用函数的使用——poll 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1.poll 的接口介紹

poll 系統(tǒng)調(diào)用和 select 類似,也是在指定時間內(nèi)輪詢一定數(shù)量的文件描述符,以測試其中是否有就緒者。poll 的原型如下:

#include <poll.h>int poll( struct pollfd *fds, nfds_t nfds, int timeout); /* poll 系統(tǒng)調(diào)用成功返回就緒文件描述符的總數(shù),超時返回 0,失敗返回-1 nfds 參數(shù)指定被監(jiān)聽事件集合 fds 的大小。 timeout 參數(shù)指定 poll 的超時值,單位是毫秒,timeout 為-1 時,poll 調(diào)用將永久阻塞,直到某個事件發(fā)生,timeout 為 0 時,poll 調(diào)用將立即返回。 *//* fds 參數(shù)是一個 struct pollfd 結(jié)構(gòu)類型的數(shù)組,它指定所有用戶感興趣的文件描述符上發(fā)生的可讀、可寫和異常等事件。pollfd 結(jié)構(gòu)體定義如下: */ 12. struct pollfd 13. { 14. int fd; // 文件描述符 15. short events; // 注冊的關(guān)注事件類型 16. short revents; // 實際發(fā)生的事件類型,由內(nèi)核填充 17. }; //其中,fd 成員指定文件描述符,events 成員告訴 poll 監(jiān)聽 fd 上的哪些事件類型。它是一系列事件的按位或,revents 成員則有內(nèi)核修改,通知應(yīng)用程序 fd 上實際發(fā)生了哪些事件。poll 支持的事件類型如下

2.示例代碼

服務(wù)端示例代碼

#define _GNU_SOURCE#include<stdio.h> #include<string.h> #include<stdlib.h> #include<unistd.h> #include<assert.h> #include<sys/socket.h> #include<arpa/inet.h> #include<sys/poll.h>#define MAX_FD 1024 #define DATALEN 128//初始化服務(wù)器的socket套接字 int InitSocket() {int sockfd = socket(AF_INET,SOCK_STREAM,0);assert(sockfd != -1);struct sockaddr_in saddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(6000);saddr.sin_addr.s_addr = inet_addr("127.0.0.1");int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));assert(res != -1);res = listen(sockfd,5);assert(res != -1);return sockfd; }//初始化記錄服務(wù)器套接字的數(shù)組 void InitPollFds(struct pollfd fds[],int n) {for(int i = 0; i < n; i++){fds[i].fd = -1;} }//將套接字描述符添加到數(shù)組中 void AddFdToPollFds(struct pollfd fds[],int n, int fd, short events) {for(int i = 0; i < n; i++){if(fds[i].fd == -1){fds[i].fd = fd;fds[i].events = events;break;}} }//接收客戶端連接 void GetClientLink(struct pollfd fds[],int n, int sockfd) {struct sockaddr_in caddr;memset(&caddr,0,sizeof(caddr));int len = sizeof(caddr);int c = accept(sockfd,(struct sockaddr*)&caddr,&len);if(c < 0){return;}else//接收連接成功,將客戶端套接字描述符和我們關(guān)心的事件類型添加到fds中{printf("cilent %d link sucess\n",c);AddFdToPollFds(fds,n,c,POLLIN | POLLRDHUP);//關(guān)心事件類型為可讀數(shù)據(jù)和客戶端關(guān)閉} }//處理客戶端數(shù)據(jù)  int DealClientData(int clifd) {char data[DATALEN] = {0};int num = recv(clifd,data,DATALEN-1,0);if(num <= 0)//讀取失敗,返回{return -1;}else{printf("%d:%s\n",clifd,data);send(clifd,"OK",2,0);}return 0; }//處理poll返回的就緒事件 void DealReadyEvent(struct pollfd fds[],int n,int sockfd) {for(int i = 0; i < n; i++){if(fds[i].fd != -1){if(fds[i].revents & POLLRDHUP)//判斷客戶端是否關(guān)閉,客戶端關(guān)閉,這里也要關(guān)閉客戶端描述符{printf("client %d over\n",fds[i].fd);close(fds[i].fd);fds[i].fd = -1;continue;}else if(fds[i].revents & POLLIN)//客戶端有可讀事件處理{if(fds[i].fd == sockfd)//如果是服務(wù)器套接字描述符有可讀事件處理,就是有客戶端連接{GetClientLink(fds,n,fds[i].fd);}else//客戶端套接字描述符有可讀事件處理,去讀取數(shù)據(jù){DealClientData(fds[i].fd);}}}} }int main() {int sockfd = InitSocket();assert(sockfd != -1);struct pollfd fds[MAX_FD];InitPollFds(fds,MAX_FD);AddFdToPollFds(fds,MAX_FD,sockfd,POLLIN);while(1){int n = poll(fds,MAX_FD,5000);//5秒時間if(n < 0)//poll失敗,服務(wù)器退出{printf("poll error\n");break;}else if(n == 0)//規(guī)定時間內(nèi)沒有就緒事件產(chǎn)生{printf("time out\n");continue;}else//有就緒事件產(chǎn)生{DealReadyEvent(fds,MAX_FD,sockfd);}}exit(0); }

客戶端示例代碼

#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<assert.h> #include<sys/socket.h> #include<arpa/inet.h>int InitSocket() {int sockfd = socket(AF_INET,SOCK_STREAM,0);assert(sockfd != -1);struct sockaddr_in saddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(6000);saddr.sin_addr.s_addr = inet_addr("127.0.0.1");int res = connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));assert(res != -1);return sockfd; }int main() {int sockfd = InitSocket();assert(sockfd != -1);while(1){printf("please input:\n");char buff[128] = {0};fgets(buff,127,stdin);if(strncmp(buff,"end",3) == 0){break;}int n = send(sockfd,buff,strlen(buff)-1,0);if(n < 0){printf("send error\n");break;}memset(buff,0,128);n = recv(sockfd,buff,127,0);if(n < 0){printf("recv error\n");break;}printf("%s\n");}close(sockfd);exit(0);}

運行結(jié)果
服務(wù)端:

客戶端1和客戶端2:

總結(jié)

以上是生活随笔為你收集整理的I/O复用函数的使用——poll的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。