函数参数说明
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd {
int fd;
short events;
short revents;
};
Instructions on Linux: poll() performs a similar task to select(2): it waits for one of a set of file descriptors to become ready to perform I/O.
POLLIN 普通或带外优先数据可读,即POLLRDNORM | POLLRDBAND
POLLRDNORM 数据可读
POLLRDBAND 优先级带数据可读
POLLPRI 高优先级可读数据
POLLOUT 普通或带外数据可写
POLLWRNORM 数据可写
POLLWRBAND 优先级带数据可写
POLLERR 发生错误
POLLHUP 发生挂起
POLLNVAL 描述字不是一个打开的文件
nfds 监控数组中有多少文件描述符需要被监控
timeout 毫秒级等待
-1:阻塞等,#define INFTIM -1 Linux中没有定义此宏
=0:立即返回,不阻塞进程
>0:等待指定毫秒数,如当前系统时间精度不够毫秒,向上取值
如果不再监控某个文件描述符时,可以把pollfd中,fd设置为-1,poll不再监控此pollfd,下次返回时,把revents设置为0
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <poll.h>
#include <errno.h>
#define MAXLINE 80
#define SERV_PORT 6666
#define OPEN_MAX 1024
int main(int argc, char *argv[])
{
int listenfd = 0;
int connfd = 0;
int sockfd = 0;
int nready;
char buf[MAXLINE],str[INET_ADDRSTRLEN];
struct pollfd client[OPEN_MAX];
listenfd = Socket(AF_INET,SOCK_STREAM,0);
int opt = 1;
setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
struct sockaddr_in servaddr;
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
Bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
Listen(listenfd,128);
memset(&client,-1,OPEN_MAX);
client[0].fd = listenfd;
client[0].events = POLLRDNORM;
int i = 0;
nfds_t maxi = 0;
for(;;)
{
nready = poll(client, maxi + 1, -1);
if(client[0].revents & POLLRDNORM)
{
struct sockaddr_in clienaddr;
ssize_t cliensize = sizeof(clienaddr);
bzero(&clienaddr,sizeof(clienaddr));
connfd = Accept(listenfd,(struct sockaddr *)&clienaddr,&cliensize);
strcpy(str,inet_ntop(AF_INET,&clienaddr.sin_addr,str,sizeof(str)));
printf("received from %s at port %d\n",str,ntohs(clienaddr.sin_port));
for(i = 1;i<OPEN_MAX;i++)
{
if(client[i].fd < 0)
{
client[i].fd = connfd;
break;
}
}
if(i == OPEN_MAX)
{
perr_exit("too many clients");
}
client[i].events = POLLRDNORM;
if(i > maxi)
{
maxi = i;
}
if(--nready <= 0)
{
continue;
}
}
for(i = 1; i <= maxi; i++)
{
sockfd = client[i].fd;
if(sockfd < 0)
{
continue;
}
short int flag = POLLRDNORM | POLLERR;
printf("client[%d].revents = 0x%x,flag = 0x%x,revents&flag = 0x%x\n",i,
client[i].revents,flag,(client[i].revents)&flag);
if(client[i].revents & (POLLRDNORM | POLLERR))
{
printf("--------------------\n");
memset(buf,0,sizeof(buf));
ssize_t n = Read(sockfd,buf,MAXLINE);
if(n < 0)
{
if(errno == ECONNRESET)
{
printf("client[%d] aborted connection\n",i);
Close(sockfd);
client[i].fd = -1;
}
else
{
perr_exit("read error");
}
}
else if(n == 0)
{
printf("client[%d] closed connection\n",i);
Close(sockfd);
client[i].fd = -1;
}
else
{
struct sockaddr_in sa;
int len = sizeof(sa);
if(!getpeername(sockfd, (struct sockaddr *)&sa, &len))
{
printf( "%s :%d-->%s\n", inet_ntoa(sa.sin_addr),ntohs(sa.sin_port),buf);
}
Write(sockfd,buf,n);
}
if(--nready <= 0)
{
break;
}
}
}
}
return 0;
}