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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

poll函数实现多路复用

發布時間:2023/11/30 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 poll函数实现多路复用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://blog.csdn.net/xluren/article/details/8206371

結構體pollfd

struct pollfd
{
int fd; ? ? ? ? ? ? ? //file descriptor
short event; ? //event of interest on fd
short reven; ?//event that occurred on fd
}

每一個pollfd結構體指定了一個被監視的文件描述符,可以傳遞多個結構體,指示poll()監視多個文件描述符。每個結構體的events域是監視該文件描述符的事件掩碼,由用戶來設置這個域。revents域是文件描述符的操作結果事件掩碼。內核在調用返回時設置這個域。events域中請求的任何事件都可能在revents域中返回。

pollfd結構體合法的事件

POLLIN
有數據可讀。
POLLRDNORM
有普通數據可讀。
POLLRDBAND
有優先數據可讀。
POLLPRI
有緊迫數據可讀。
POLLOUT
寫數據不會導致阻塞。
POLLWRNORM
寫普通數據不會導致阻塞。
POLLWRBAND
寫優先數據不會導致阻塞。
POLLMSG
SIGPOLL 消息可用。
此外,revents域中還可能返回下列事件:
POLLER
指定的文件描述符發生錯誤。
POLLHUP
指定的文件描述符掛起事件。
POLLNVAL
指定的文件描述符非法。
這些事件在events域中無意義,因為它們在合適的時候總是會從revents中返回。使用poll()和select()不一樣,你不需要顯式地請求異常情況報告。
POLLIN | POLLPRI等價于select()的讀事件,POLLOUT |POLLWRBAND等價于select()的寫事件。POLLIN等價于POLLRDNORM |POLLRDBAND,而POLLOUT則等價于POLLWRNORM。
例如,要同時監視一個文件描述符是否可讀和可寫,我們可以設置 events為POLLIN |POLLOUT。在poll返回時,我們可以檢查revents中的標志,對應于文件描述符請求的events結構體。如果POLLIN事件被設置,則文件描述符可以被讀取而不阻塞。如果POLLOUT被設置,則文件描述符可以寫入而不導致阻塞。這些標志并不是互斥的:它們可能被同時設置,表示這個文件描述符的讀取和寫入操作都會正常返回而不阻塞。
timeout參數指定等待的毫秒數,無論I/O是否準備好,poll都會返回。timeout指定為負數值表示無限超時;timeout為0指示poll調用立即返回并列出準備好I/O的文件描述符,但并不等待其它的事件。這種情況下,poll()就像它的名字那樣,一旦選舉出來,立即返回。

函數原型

int poll(struct pollfd fdarray[], nfds_t nfds, int timeout);
poll返回值和錯誤代碼
成功時,poll()返回結構體中revents域不為0的文件描述符個數;如果在超時前沒有任何事件發生,poll()返回0;失敗時,poll()返回-1,并設置errno為下列值之一:
EBADF
一個或多個結構體中指定的文件描述符無效。
EFAULT
fds指針指向的地址超出進程的地址空間。
EINTR
請求的事件之前產生一個信號,調用可以重新發起。
EINVAL
nfds參數超出PLIMIT_NOFILE值。
ENOMEM
可用內存不足,無法完成請求。

以上理論摘自http://www.cnblogs.com/nathan-1988/archive/2012/07/01/2571786.html?謝謝~~~

代碼如下所示:

[cpp]?view plain?copy
  • #include?<stdio.h>??
  • #include?<stdlib.h>??
  • #include?<unistd.h>??
  • #include?<errno.h>??
  • #include?<string.h>??
  • #include?<sys/types.h>??
  • #include?<sys/socket.h>??
  • #include?<netinet/in.h>??
  • #include?<arpa/inet.h>??
  • #include?<poll.h>??
  • #define?MYPORT?6666????//?the?port?users?will?be?connecting?to??
  • ??
  • #define?BACKLOG?5?????//?how?many?pending?connections?queue?will?hold??
  • #ifndef?INFTIM??
  • #define?INFTIM?-1??
  • #endif??
  • #define?BUF_SIZE?1024??
  • #define?MAXLINE?100??
  • #define?MAXCLIENT?5??
  • int?fd_access[BACKLOG];????//?accepted?connection?fd??
  • int?conn_amount;????//?current?connection?amount??
  • ??
  • int?main(void)??
  • {??
  • ????????int?sock_fd,?new_fd,len,conn_no;??//?listen?on?sock_fd,?new?connection?on?new_fd??
  • ????????struct?sockaddr_in?server_addr;????//?server?address?information??
  • ????????struct?sockaddr_in?client_addr;?//?connector's?address?information??
  • ????????socklen_t?sin_size;??
  • ????????char?buf[BUF_SIZE];??
  • ????????int?result;??
  • ????????int?i;??
  • ????????int?maxsock=0;??
  • ????????int?conn_fd;??
  • ????????struct?pollfd?client[MAXCLIENT];??
  • ????????if?((sock_fd?=?socket(AF_INET,?SOCK_STREAM,?0))?==?-1)???
  • ????????{??
  • ????????????????perror("socket");??
  • ????????????????exit(1);??
  • ????????}???
  • ????????server_addr.sin_family?=?AF_INET;?????????//?host?byte?order??
  • ????????server_addr.sin_port?=?htons(MYPORT);?????//?short,?network?byte?order??
  • ????????server_addr.sin_addr.s_addr?=?INADDR_ANY;?//?automatically?fill?with?my?IP??
  • ????????memset(server_addr.sin_zero,?'\0',?sizeof(server_addr.sin_zero));??
  • ????????if?(bind(sock_fd,?(struct?sockaddr?*)&server_addr,?sizeof(server_addr))?==?-1)???
  • ????????{??
  • ????????????????perror("bind");??
  • ????????????????exit(1);??
  • ????????}??
  • ????????if?(listen(sock_fd,?BACKLOG)?==?-1)???
  • ????????{??
  • ????????????????perror("listen");??
  • ????????????????exit(1);??
  • ????????}??
  • ????????printf("listen?port?%d\n",?MYPORT);??
  • ??
  • ????????sin_size?=?sizeof(client_addr);??
  • ????????client[0].fd=sock_fd;??
  • ????????client[0].events=POLLIN;??
  • ????????for(i=1;i<MAXCLIENT;i++)??
  • ????????????????client[i].fd=-1;??
  • ????????while?(1)???
  • ????????{??
  • ????????????????printf("helo\n");??
  • ????????????????result=poll(client,maxsock+1,INFTIM);??
  • ????????????????if(client[0].revents&POLLIN)??
  • ????????????????{??
  • ????????????????????????new_fd=accept(sock_fd,(struct?sockaddr*)&client_addr,&sin_size);??
  • ????????????????????????for(i?=?1;?i?<?MAXCLIENT;++i)??
  • ????????????????????????{??
  • ????????????????????????????????if(?client[i].fd?<?0?)??
  • ????????????????????????????????{?????????
  • ????????????????????????????????????????client[i].fd?=?new_fd;??
  • ????????????????????????????????????????client[i].events?=?POLLIN;//POLLRDNORM;??
  • ????????????????????????????????????????break;??
  • ????????????????????????????????}??
  • ????????????????????????}??
  • ????????????????????????if(?i?==?MAXCLIENT)??
  • ????????????????????????{??
  • ????????????????????????????????printf("too?many?clients");???
  • ????????????????????????????????exit(1);??
  • ????????????????????????}??
  • ????????????????????????if(?i?>?maxsock?)??
  • ????????????????????????????????maxsock?=?i;??
  • ????????????????????????if(?--result<=?0?)??
  • ????????????????????????????????continue;??
  • ????????????????}??
  • ????????????????for(i?=?1;?i?<=?maxsock;?i++)??
  • ????????????????{??
  • ????????????????????????if(?(conn_fd?=?client[i].fd)?<?0)??
  • ????????????????????????????????continue;??
  • ????????????????????????if(client[i].revents?&?(POLLIN?|?POLLERR))??
  • ????????????????????????{??
  • ????????????????????????????????if(?(len?=?read(conn_fd,?buf,?MAXLINE))?<?0)???
  • ????????????????????????????????{??
  • ????????????????????????????????????????if(?errno?==?ECONNRESET)??
  • ????????????????????????????????????????{??
  • ????????????????????????????????????????????????close(conn_fd);??
  • ????????????????????????????????????????????????client[i].fd?=?-1;??
  • ????????????????????????????????????????}??
  • ????????????????????????????????????????else??
  • ????????????????????????????????????????????????perror("read?error");??
  • ????????????????????????????????}??
  • ????????????????????????????????else?if(len?==?0)??
  • ????????????????????????????????{??
  • ????????????????????????????????????????close(conn_fd);??
  • ????????????????????????????????????????client[i].fd?=?-1;??
  • ????????????????????????????????}??
  • ????????????????????????????????else??
  • ????????????????????????????????????????printf("%s\n",buf);??
  • ????????????????????????????????if(--conn_no?<=?0)??
  • ????????????????????????????????????????break;??
  • ??
  • ????????????????????????}??
  • ????????????????}??
  • ????????}??
  • ????????exit(0);??
  • }??
  • ??
  • (END)???


  • 以上是服務器端

    客戶端代碼見http://blog.csdn.net/xluren/article/details/8043484#t15


    總結

    以上是生活随笔為你收集整理的poll函数实现多路复用的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。