2.1)select函數文法: /* According to POSIX 1003.1-2001 */ #include <sys/select.h> /* According to earlier standards */ #include <sys/time.h> #include <sys/types.h> #include <unistd.h> int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); int pselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask); FD_CLR(int fd, fd_set *set); FD_ISSET(int fd, fd_set *set); FD_SET(int fd, fd_set *set); FD_ZERO(fd_set *set);
DESCRIPTION The functions select and pselect wait for a number of file descriptors to change status.
RETURN VALUE On success, select and pselect return
the number of descriptors contained in the descriptor sets, which may be
zero if the timeout expires before anything interesting happens. On
error, -1 is returned, and errno is set appropriately; the sets and timeout become undefined, so do not rely on their contents after an error.
樣本:#include <stdio.h>#include <sys/time.h>#include <sys/types.h>#include <unistd.h>int main (void){ fd_set rfds; struct timeval tv; int retval; /* Watch stdin (fd 0) to see when it has input. */ FD_ZERO (&rfds); FD_SET (0, &rfds); FD_SET (1, &rfds); FD_SET (2, &rfds); FD_SET (4, &rfds); /* Wait up to five seconds. */ tv.tv_sec = 5; tv.tv_usec = 0; retval = select (2, &rfds, NULL, NULL, &tv); if (retval == -1) perror ("select()"); else if (retval) { printf ("Data is available now./n"); printf( "retval=%d/n",retval); } /* FD_ISSET(0, &rfds) will be true. */ else printf ("No data within five seconds./n"); return 0;}
2.2)epollSYNOPSIS#include <sys/epoll.h> int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)int epoll_create(int size)int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout)
樣本:#include <iostream>#include <sys/socket.h>#include <sys/epoll.h>#include <netinet/in.h>#include <arpa/inet.h>#include <fcntl.h>#include <unistd.h>#include <stdio.h>#include <errno.h> #define MAXLINE 10#define OPEN_MAX 100#define LISTENQ 20#define SERV_PORT 5555#define INFTIM 1000 void setnonblocking(int sock){ int opts; opts = fcntl(sock, F_GETFL); if (opts < 0) { perror("fcntl(sock, GETFL)"); exit(1); } opts = opts|O_NONBLOCK; if (fcntl(sock, F_SETFL, opts) < 0) { perror("fcntl(sock, SETFL, opts)"); exit(1); }} int main(){ int i, maxi, listenfd, connfd, sockfd, epfd, nfds; ssize_t n = 0; char line[MAXLINE]; int l_sinSize = 0; l_sinSize = sizeof(struct sockaddr); //聲明epoll_event結構體的變數,ev用於註冊事件,數組用於回傳要處理的事件 struct epoll_event ev, events[20];//-------------------- //產生用於處理accept的epoll專用的檔案描述符 epfd = epoll_create(256);//----------------------------- struct sockaddr_in clientaddr; struct sockaddr_in serveraddr; listenfd = socket(AF_INET, SOCK_STREAM, 0); //把socket設定為非阻塞方式 setnonblocking(listenfd);//----------------------------- //設定與要處理的事件相關的檔案描述符 ev.data.fd = listenfd;//-------------------------------- //設定要處理的事件類型 ev.events = EPOLLIN|EPOLLET;//-------------------------- //註冊epoll事件 epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev);//--------------------- bzero(&serveraddr, sizeof(struct sockaddr_in)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons(SERV_PORT); bind(listenfd, (struct sockaddr *)(&serveraddr), sizeof(struct sockaddr)); listen(listenfd, LISTENQ); maxi = 0; for ( ; ; ) { //等待epoll事件的發生 nfds=epoll_wait(epfd,events,20,500);//--------------------------- //處理所發生的所有事件 for (i = 0; i < nfds; ++i) { if (events[i].data.fd == listenfd) { connfd = accept(listenfd, (struct sockaddr *)(&clientaddr), (socklen_t *)&l_sinSize);//------------ if (connfd < 0) { perror("connfd < 0"); exit(1); } setnonblocking(connfd); char* str = inet_ntoa(clientaddr.sin_addr); std::cout<<"connect from "<<str<<std::endl; //設定用於讀操作的檔案描述符 ev.data.fd = connfd; //設定用於注測的讀操作事件 ev.events = EPOLLIN|EPOLLET; //註冊ev epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev); } else if (events[i].events&EPOLLIN) { if ((sockfd = events[i].data.fd) < 0) { continue; } if ((n = read(sockfd, line, MAXLINE)) < 0) { if (errno == ECONNRESET) { close(sockfd); events[i].data.fd = -1; } else { std::cout<<"readline error"<<std::endl; } } else if (n == 0) { close(sockfd); events[i].data.fd = -1; } //設定用於寫操作的檔案描述符 ev.data.fd = sockfd; //設定用於注測的寫操作事件 ev.events = EPOLLOUT|EPOLLET; //修改sockfd上要處理的事件為EPOLLOUT epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev); } else if(events[i].events&EPOLLOUT) { sockfd = events[i].data.fd; ssize_t l_writeSize = write(sockfd, line, n); std::cout<<"write "<<l_writeSize<<std::endl; //設定用於讀操作的檔案描述符 ev.data.fd = sockfd; //設定用於注測的讀操作事件 ev.events = EPOLLIN|EPOLLET; //修改sockfd上要處理的事件為EPOLIN epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev); } } }}