生活随笔
收集整理的這篇文章主要介紹了
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];?????? int?conn_amount;?????? ?? int?main(void)?? {?? ????????int?sock_fd,?new_fd,len,conn_no;???? ????????struct?sockaddr_in?server_addr;?????? ????????struct?sockaddr_in?client_addr;??? ????????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;??????????? ????????server_addr.sin_port?=?htons(MYPORT);??????? ????????server_addr.sin_addr.s_addr?=?INADDR_ANY;??? ????????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;?? ????????????????????????????????????????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函数实现多路复用的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。