与select相比,poll能突破1024个文件描述符的限制.
server_poll.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <poll.h>
#define MAXLINE 80
#define SERV_PORT 6666
#define OPEN_MAX 1024
int main()
{
//1.创建socket
struct sockaddr_in serv_addr, clnt_addr;
int lfd, cfd, sockfd;
socklen_t clnt_size;
int i, j, n, nready, maxi;
struct pollfd clients[OPEN_MAX];
lfd = socket(AF_INET, SOCK_STREAM, 0);
int opt = 1;
setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(SERV_PORT);
bind(lfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(lfd, 128);
clients[0].fd = lfd;
clients[0].events = POLLIN; //监听读事件
for(i = 1; i < OPEN_MAX; i++){
clients[i].fd = -1;
}
maxi = 0;
clnt_size = sizeof(clnt_addr);
char readBuf[1024];
while(1){
nready = poll(clients, maxi+1, -1);
printf("nready = %d\n", nready);
//有新的连接
if(clients[0].revents & POLLIN){
printf("有新的连接...\n");
cfd = accept(lfd, (struct sockaddr*)&clnt_addr, &clnt_size);
printf("cfd = %d\n", cfd);
for(i = 1; i < OPEN_MAX; i++){
if(clients[i].fd < 0){
clients[i].fd = cfd;
clients[i].events = POLLIN;
break;
}
}
if(i == OPEN_MAX){
printf("too many connection\n");
exit(1);
}
maxi = (i > maxi ? i : maxi);
if(--nready <= 0){
continue;
}
}
//已建立的连接发送数据
printf("maxi = %d\n", maxi);
for(i = 1; i <= maxi; i++){
if((sockfd = clients[i].fd) < 0){
printf("sockfd 小于0\n");
continue;
}
if(clients[i].revents & POLLIN){
if((n = read(sockfd, readBuf, sizeof(readBuf))) < 0){
if(errno == ECONNRESET){
printf("客户端 %d 重置连接\n", i+1);
close(sockfd);
clients[i].fd = -1;
}else{
perror("read error");
exit(1);
}
}else if(n == 0){ //客户端关闭连接
printf("客户端 %d 关闭连接\n", i+1);
close(sockfd);
clients[i].fd = -1;
}else if(n > 0){ //有数据
for(j = 0; j < n; j++){
readBuf[j] = toupper(readBuf[j]);
}
write(sockfd, readBuf, n);
write(STDOUT_FILENO, readBuf, n); //写到标准输出
}
}
if(--nready <= 0){
break;
}
}
}
}