poll函数与select类似,最显著的区别是提供fd的方式不一样。
要让poll监控文件描述符的话,需要提供一个struct pollfd的数组。
struct pollfd的内容如下
/* Data structure describing a polling request. */
struct pollfd
{
int fd; /* File descriptor to poll. */
short int events; /* Types of events poller cares about. */
short int revents; /* Types of events that actually occurred. */
};
其中fd是文件描述符,events是需要监控的事件,revents是实际发生的事件。
当监控的事件时,poll函数会修改struct pollfd数组里每个pollfd.revents。
events和revents可选的值如下
/* Event types that can be polled for. These bits may be set in `events'
to indicate the interesting event types; they will appear in `revents'
to indicate the status of the file descriptor. */
#define POLLIN 0x001 /* There is data to read. */
#define POLLPRI 0x002 /* There is urgent data to read. */
#define POLLOUT 0x004 /* Writing now will not block. */
#if defined __USE_XOPEN || defined __USE_XOPEN2K8
/* These values are defined in XPG4.2. */
# define POLLRDNORM 0x040 /* Normal data may be read. */
# define POLLRDBAND 0x080 /* Priority data may be read. */
# define POLLWRNORM 0x100 /* Writing now will not block. */
# define POLLWRBAND 0x200 /* Priority data may be written. */
#endif
#ifdef __USE_GNU
/* These are extensions for Linux. */
# define POLLMSG 0x400
# define POLLREMOVE 0x1000
# define POLLRDHUP 0x2000
#endif
/* Event types always implicitly polled for. These bits need not be set in
`events', but they will appear in `revents' to indicate the status of
the file descriptor. */
#define POLLERR 0x008 /* Error condition. */
#define POLLHUP 0x010 /* Hung up. */
#define POLLNVAL 0x020 /* Invalid polling request. */
下面这个例子监听4444端口,结合poll来管理多个网络连接。
客户端用普通的telnet就可以
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <poll.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int do_listen(char* ip, int port, int backlog)
{
int fd = 0;
if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
{
puts(strerror(errno));
exit(errno);
}
int opt = 1;
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, ip, &servaddr.sin_addr);
servaddr.sin_port = htons(port);
if(bind(fd, (struct sockaddr*)&servaddr, sizeof(servaddr) ) < 0)
{
puts(strerror(errno));
exit(errno);
}
listen(fd, backlog);
return fd;
}
int do_poll(int sock, int maxfd)
{
struct sockaddr_in clientaddr;
socklen_t socklen = sizeof(clientaddr);
struct pollfd fds[maxfd];
int max = 2;
int ok = 0;
fds[0].fd = sock;
fds[0].events = POLLIN;
int i = 0;
for(; ++i < maxfd; fds[i].fd=-1);
int cnt = 0;
char buf[BUFSIZ];
char hello[10] = "hello";
int conn = 0;
int added = 0;
while(1)
{
int ok = poll(fds, max, -1);
printf("poll %d\n", ok);
if(ok < 0)
{
printf("poll error: %s\n", strerror(errno));
exit(errno);
}
if(fds[0].revents & POLLIN == POLLIN)
{
if((conn = accept(sock, (struct sockaddr*)&clientaddr, &socklen)) < 0)
{
if(errno == EINTR) continue;
printf("accept error: %s\n", strerror(errno));
exit(errno);
}
for(i=1; i<maxfd; i++)
{
if(fds[i].fd < 0)
{
fds[i].fd = conn;
fds[i].events = POLLIN;
added = 1;
if(i>=max) max = i+1;
break;
}
}
if(added == 0)
{
printf("drop connect: %s:%d\n", inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port);
}
added = 0;
printf("accept: %d, %s:%d\n", conn, inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port);
}
else
{
// check all fd
printf("from client...\n");
for(i=1; i<maxfd; i++)
{
if(fds[i].fd < 0) continue;
if(fds[i].revents & POLLIN)
{
cnt = read(fds[i].fd, buf, BUFSIZ);
if(cnt == 0 || *buf == EOF)
{
close(fds[i].fd);
fds[i].fd = -1;
printf("client exit\n");
continue;
}
buf[cnt] = '\0';
printf("from client: %s", buf);
write(fds[i].fd, hello, 5);
write(fds[i].fd, buf, cnt);
}
}
}
}
return 0;
}
int main()
{
int sock = do_listen("0.0.0.0", 4444, 100);
do_poll(sock, 1024);
close(sock);
return 0;
}
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26239116/viewspace-2075383/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/26239116/viewspace-2075383/