1.Epoll
常用操作:
#include <sys/epoll.h>
1,1 int epoll_create(int size);
返回值:On success, these system calls return a non-negative file descriptor.
1.2 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
返回值:When successful, epoll_ctl() returns 0.
這個函數通過之前創建的epfd來控制epoll,需要一些操作類型碼(op),來控制目標的描述符。
This system call performs control operations on the epoll instance
referred to by the file descriptor epfd. It requests that the operation op be performed for the target file descriptor- fd.
Valid values for the op argument are :
EPOLL_CTL_ADD
Register the target file descriptor fd on the epoll instance
referred to by the file descriptor epfd and associate the event
event with the internal file linked to fd.
EPOLL_CTL_MOD
Change the event event associated with the target file descrip-
tor fd.
EPOLL_CTL_DEL
//////////////////////////////////////////////////////////////////////////
typedef union epoll_data {
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;
struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
The events member is a bit set composed using the following available event types:
EPOLLIN :表示對應的文件描述符可以讀(包括對端SOCKET正常關閉);
EPOLLOUT:表示對應的文件描述符可以寫;
EPOLLPRI:表示對應的文件描述符有緊急的數據可讀(這裏應該表示有帶外數據到來);
EPOLLERR:表示對應的文件描述符發生錯誤;
EPOLLHUP:表示對應的文件描述符被掛斷;
EPOLLET: 將EPOLL設爲邊緣觸發(Edge Triggered)模式,這是相對於水平觸發(Level Triggered)來說的。
EPOLLONESHOT:只監聽一次事件,當監聽完這次事件之後,如果還需要繼續監聽這個socket的話,需要再次把這個socket加入到EPOLL隊列裏
1.3 int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
返回值:
When successful, epoll_wait() returns the number of file descriptors
ready for the requested I/O, or zero if no file descriptor became ready
during the requested timeout milliseconds.
//描述
The epoll_wait() system call waits for events on the epoll instance
referred to by the file descriptor epfd. The memory area pointed to by
events will contain the events that will be available for the caller.
Up to maxevents are returned by epoll_wait(). The maxevents argument
must be greater than zero.
The call waits for a maximum time of timeout milliseconds. Specifying
a timeout of -1 makes epoll_wait() wait indefinitely, while specifying
a timeout equal to zero makes epoll_wait() to return immediately even
if no events are available (return code equal to zero)
示例代碼:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
int main()
{
int socketfd, ret, i;
socketfd = socket(AF_INET,SOCK_STREAM,0);
if(socketfd == -1)
{
perror("func socket\n");
exit(0);
}
struct sockaddr_in srvaddr;
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = htons(8001);
srvaddr.sin_addr.s_addr = inet_addr("192.168.1.103");
if(bind(socketfd,(struct sockaddr*)&srvaddr,sizeof(srvaddr))<0)
{
perror("func bind\n");
exit(0);
}
if(listen(socketfd,SOMAXCONN)<0)
{
perror("func listen\n");
exit(0);
}
struct epoll_event ev,events[20];
int epollfd, nfds;
struct sockaddr_in peeraddr;
socklen_t peerlen = sizeof(peeraddr);
char revbuf[1024] = {0};
unsigned int connfd;
epollfd = epoll_create(100);
ev.data.fd = socketfd;
ev.events = EPOLLIN|EPOLLET;
epoll_ctl(epollfd,EPOLL_CTL_ADD,socketfd,&ev);
while(1)
{
nfds = epoll_wait(epollfd, events, 20, 500);
for(i=0; i<nfds; i++)
{
if (events[i].data.fd == socketfd) {
connfd = accept(socketfd,(struct sockaddr*)&peeraddr,
(socklen_t*)&peerlen);
if (connfd == -1) {
printf("accept");
exit(0);
}
printf("child process socketfd:%d, connfd%d\n",socketfd,connfd);
printf("peeradd:%s \npeerport:%d\n",inet_ntoa(peeraddr.sin_addr),
ntohs(peeraddr.sin_port));
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = connfd;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd,
&ev) == -1) {
perror("epoll_ctl: conn_sock");
exit(EXIT_FAILURE);
}
}else if(events[i].events & EPOLLIN){
ret = read(events[i].data.fd,revbuf,sizeof(revbuf));
if(ret == 0)
{
printf("clt close \n");
//exit(0);
}
fputs(revbuf,stdout);
//memset(revbuf,0,sizeof(revbuf));
}
}
}
return 0;
}
2.poll
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};
The field fd contains a file descriptor for an open file.
The field events is an input parameter, a bit mask specifying the
events the application is interested in.
The field revents is an output parameter, filled by the kernel with the
events that actually occurred.
POLLIN There is data to read.
POLLPRI
There is urgent data to read (e.g., out-of-band data on
TCP socket; pseudo-terminal master in packet mode has
seen state change in slave).
POLLOUT
Writing now will not block.
POLLRDHUP (since Linux 2.6.17)
Stream socket peer closed connection, or shut down writ-
ing half of connection. The _GNU_SOURCE feature test
macro must be defined in order to obtain this definition.
POLLERR
Error condition (output only).
POLLHUP
Hang up (output only).
POLLNVAL
Invalid request: fd not open (output only).
When compiling with _XOPEN_SOURCE defined, one also has the following,
which convey no further information beyond the bits listed above:
POLLRDNORM
Equivalent to POLLIN.
POLLRDBAND
Priority band data can be read (generally unused on
Linux).
POLLWRNORM
Equivalent to POLLOUT.
POLLWRBAND
Priority data may be written.
返回值:
On success, a positive number is returned; this is the number of struc-
tures which have non-zero revents fields (in other words, those
descriptors with events or errors reported). A value of 0 indicates
that the call timed out and no file descriptors were ready. On error,
-1 is returned, and errno is set appropriately.
3.select
#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
void FD_CLR(int fd, fd_set *set);
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);
返回值:
On success, select() return the number of file descriptors contained
in the three returned descriptor sets (that is, the total number
of bits that are set in readfds, writefds, exceptfds)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.
NOTE:
nfds is the highest-numbered file descriptor in any of the three sets,
plus 1.
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
示例代碼:
#include <stdio.h>
#include <stdlib.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);
/* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
/* Don’t rely on the value of tv now! */
if (retval == -1)
perror("select()");
else if (retval)
printf("Data is available now.\n");
/* FD_ISSET(0, &rfds) will be true. */
else
printf("No data within five seconds.\n");
exit(EXIT_SUCCESS);
}