1、poll的优缺点
poll的优点
1)poll() 不要求开发者计算最大文件描述符加一的大小。
2)poll() 在应付大数目的文件描述符的时候速度更快,相比于select。
3)它没有最大连接数的限制,原因是它是基于链表来存储的。
poll的缺点
1)大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义。
2)与select一样,poll返回后,需要轮询pollfd来获取就绪的描述符。
2、poll服务器的简单实现
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<poll.h>
#include<string.h>
#define POLLFD_SIZE 1024
struct pollfd array_fd[POLLFD_SIZE];
void pd_action(int index)
{
if(array_fd[index].revents & POLLIN){
char buf[1024];
memset(buf,0,sizeof(buf));
ssize_t s = read(array_fd[index].fd,0,sizeof(buf)-1);
if(s > 0){
buf[s] = 0;
printf("client say:%s\n",buf);
fflush(stdout);
array_fd[index].events = POLLOUT;
}else{
printf("client quit!\n");
fflush(stdout);
close(array_fd[index].fd);
array_fd[index].fd = -1;//文件描述符初始化为默认值
}
}else if(array_fd[index].revents & POLLOUT){
const char*msg = "HTTP/1.1 200 OK\r\n\r\n<html><br/><h1>hello poll</h1></html>";
write(array_fd[index].fd,msg,strlen(msg));
array_fd[index].events = POLLIN;
}
}
int startup(const char *_ip,int _port)
{
int sock = socket(AF_INET,SOCK_STREAM,0);
if(sock < 0){
perror("socket");
exit(1);
}
int opt = 1;
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_addr.s_addr = inet_addr(_ip);
local.sin_port = htons(_port);
if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0){
perror("bind");
exit(2);
}
if(listen(sock,10) < 0){
perror("listen");
exit(3);
}
return sock;
}
static void usage(const char *proc)
{
printf("usage:%s[local_ip][local_port]\n",proc);
}
int main(int argc,char *argv[])
{
if(argc != 3){
usage(argv[0]);
return 1;
}
int listen_sock = startup(argv[1],atoi(argv[2]));
array_fd[0].fd = listen_sock;
int i = 0;
for(;i < POLLFD_SIZE;i++){
array_fd[i].fd = -1;
}
int timeout = -1;
while(1){
switch(poll(array_fd,POLLFD_SIZE,timeout)){
case 0:
printf("timeout....\n");
break;
case -1:
perror("poll\n");
break;
default:
{
int j = 0;
for(;j < POLLFD_SIZE;j++)
{
if(j == 0 && array_fd[j].revents & POLLIN){
struct sockaddr_in client;
socklen_t len = sizeof(client);
int newfd = accept(listen_sock,(struct sockaddr*)&client,&len);
if(newfd < 0){
perror("accept\n");
continue;
}else{
printf("get a new client:(%s:%d)\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
int k = 0;
for(;k < POLLFD_SIZE;k++){
if(array_fd[k].fd < 0){
array_fd[k].fd = newfd;
array_fd[k].events = POLLOUT;
break;
}
}
if(k == POLLFD_SIZE)
{
close(newfd);
break;
}
}
}else if(j != 0){
pd_action(j);
}else{
}
}
}
break;
}
}
close(listen_sock);
return 0;
}