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);
}