poll函数原型
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};
//fds 监听数组
//nfds 监听数组的实际个数
//timeout -1 无限超时
// 0 立即返回
// >0 超时返回
//返回值 >0结构体中revents域不为0的文件描述符个数
// 0没有任何事件发生
// -1错误
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
示例
#include "wrap.h"
#include "stdio.h"
#include "stdlib.h"
#include "netinet/ip.h"
#include "sys/poll.h"
#include "unistd.h"
#include "strings.h"
#include "ctype.h"
#include "arpa/inet.h"
#define PORT 8888
#define OPEN_MAX 1000
void server_select()
{
int lfd = 0;
int cfd = 0;
int lNum = 0,i,n;
struct sockaddr_in serv_addr,clit_addr;
socklen_t clit_addr_len;
char buf[BUFSIZ];
char clit_ip[1024];
bzero(&serv_addr,sizeof(serv_addr));
bzero(&clit_addr,sizeof(clit_addr));
bzero(buf,sizeof(char)*BUFSIZ);
bzero(clit_ip,sizeof(char)*1024);
clit_addr_len = sizeof(clit_addr);
//设置服务器地址和端口
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
//创建socket
lfd = Socket(AF_INET,SOCK_STREAM,0);
int opt = 1;//设置端口复用
Setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,sizeof(opt));
Bind(lfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));//绑定服务器地址 端口
Listen(lfd,128);
struct pollfd pfds[OPEN_MAX];
//初始化客户连接描述符
for (i = 1;i < OPEN_MAX;i++)
pfds[i].fd = -1;
pfds[0].fd = lfd;
pfds[0].events = POLLIN;
pfds[0].revents = 0;
int maxi=0;
while (1)
{
lNum = poll(pfds,maxi+1,0);
if (lNum<0)
{
sys_err("poll error");
}else
{
if(pfds[0].revents & POLLIN)
{
cfd = Accept(lfd,(struct sockaddr*)&clit_addr,&clit_addr_len);//连接 非阻塞
printf("client ip:%s,port:%d\n",
inet_ntop(AF_INET,&clit_addr.sin_addr.s_addr,clit_ip,1024),
ntohs(clit_addr.sin_port));
//将新的连接描述符添加到数组中
for (i = 1;i < OPEN_MAX;i++)
{
if (pfds[i].fd < 0)
{
pfds[i].fd = cfd;
break;
}
}
if (i == OPEN_MAX)
{
fprintf(stderr,"too many clients.\n");
exit(1);
}
//将新的描述符添加到读描述符集合中
pfds[i].events = POLLIN;
//记录客户连接套接字的个数
maxi = (i > maxi ? i : maxi);
}
if(lNum == 1)
{
continue;
}
}
for(i=1;i<=maxi;++i)//遍历处理读集合中的描述符请求
{
if (pfds[i].fd < 0)
continue;
//测试客户描述符是否准备好
if (pfds[i].revents & POLLIN)
{
n = read(pfds[i].fd,buf,sizeof(buf));
if(n == 0)
{
Close(pfds[i].fd);
printf("client %d exit\n",ntohs(clit_addr.sin_port));
continue;
}
write(STDOUT_FILENO,buf,n);
for(int j=0;j<n;++j)
{
buf[j] = toupper(buf[j]);
}
write(pfds[i].fd,buf,n);
}
}
}
Close(lfd);
Close(cfd);
}
int main(int args,char *argc[])
{
server_select();
return 0;
}