poll:
int poll(struct pollfd* fds,nfds_t nfds,int timeout)
fds: 监听的文件描述符 【数组】
struct pollfd {
int fd 待监听的文件描述符
short events 待监听的文件描述符对应的监听事件
取值:POLLIN、POLLOUT、POLLERR
short revents 传入时,给 0 ;若果满足对应事件的话,
返回非0 --》POLLIN、POLLOUT POLLERR
}
nfds: 监听数组的, 实际有效监听个数
timeout: 》0 超时时长 单位毫秒
扫描二维码关注公众号,回复:
9294149 查看本文章
-1 阻塞等待
0 不阻塞
返回值:返回对应监听事件的文件描述符 总个数
优点:
自带数组结构。可以将 监听事件集合 和 返回事件集合分离
拓展监听上限。超出 1024 限制
缺点: 不能跨平台
无法直接定位满足监听事件的文件描述符。 编码难度大
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<ctype.h>
#include<errno.h>
#include<poll.h>
#define MAXLINE 80
#define SERV_PORT 8000
#define OPEN_MAX 1024
int main(){
int i,j,maxi,listenfd,connfd,sockfd;
int nready;
size_t n;
char buf[MAXLINE],str[INET_ADDRSTRLEN];
socklen_t clilen;
struct pollfd client[OPEN_MAX];
struct sockaddr_in cliaddr,servaddr;
listenfd = socket(AF_INET,SOCK_STREAM,0);
int opt =1;
setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
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);
client[0].fd = listenfd; //要监听的第一个文件描述符
client[0].events = POLLIN; //listenfd 监听普通读事件
for(i=1;i<OPEN_MAX;++i){
client[i].fd= -1; //用-1 初始化client【】里剩余元素
}
maxi = 0;
for(;;){
nready = poll(client,maxi+1,-1); //阻塞监听是否有客户端连接请求
if(client[0].revents & POLLIN){
clilen = sizeof(cliaddr);
connfd = accept(listenfd,(struct sockaddr*)&cliaddr,&clilen); //接受客户端请求 不阻塞
printf("receiverd from %s PORT %d\n",
inet_ntop(AF_INET,&cliaddr.sin_addr,str,sizeof(str)),
ntohs(cliaddr.sin_port));
for(i=1;i<OPEN_MAX;++i){
if(client[i].fd<0){
client[i].fd = connfd;
break;
}
}
client[i].events = POLLIN;
if(i>maxi)
maxi =i;
if(--nready<=0)
continue;
}
for(i =1;i<=maxi;++i){
if((sockfd=client[i].fd)<0)
continue;
if(client[i].revents & POLLIN){
if((n=read(sockfd,buf,MAXLINE))<0){
if(errno = ECONNRESET){ //收到RST标志
printf("client[%d] aborted connection\n",i);
close(sockfd);
client[i].fd = -1;
}else{
perror("read error");
exit(1);
}
}else if(n==0){
printf("client[%d] closed connection\n",i);
close(sockfd);
client[i].fd = -1;
}else{
for(j=0;j<n;++j)
buf[j]=toupper(buf[j]);
write(sockfd,buf,n);
write(STDOUT_FILENO,buf,n);
}
}
}
}
return 0;
}