poll模型与select模型大同小异,也是一种轮询模型,不同之处是poll模型更加方便,不像select模型一样,每次都去设置fd_set的值,select模型最多能打开的文件描述符为1024个,即使使用ulimit -n xxx也无法改变,但是poll模型可以突破1024的限制,只需更改系统的ulimit -n配置即可。
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <poll.h>
#include <errno.h>
#define TCP_PORT 9999
#define SOCK_NUM 2048
int main()
{
struct pollfd socketfd[SOCK_NUM];
int socket_ser,socket_accept;
struct sockaddr_in addr,addr_c;
int maxfd;
char recbuf[1500];
socket_ser = socket(AF_INET,SOCK_STREAM,0);
bzero(&addr,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(TCP_PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(socket_ser,(struct sockaddr *)&addr,sizeof(addr));
listen(socket_ser,128);
socketfd[0].fd = socket_ser;
socketfd[0].events = POLL_IN;
for (int j = 1; j < SOCK_NUM; ++j) {
socketfd[j].fd = -1;
}
maxfd = 0;
while (1)
{
//监听maxfd+1个文件描叙符的读
int num = poll(socketfd,maxfd+1,-1);//-1代表阻塞;
if (socketfd[0].revents & POLLIN)
{
int i;
for (i = 1; i < SOCK_NUM; ++i) {
if(socketfd[i].fd<0)
break;
}
bzero(&addr_c,sizeof(addr_c));
int len = sizeof(addr_c);
socketfd[i].fd = accept(socket_ser,(struct sockaddr*)&addr_c,(socklen_t*)&len);
if (i > maxfd)
{
maxfd = i;
}
socketfd[i].events = POLLIN;
num--;
char recip[16];
printf("Ip is %s,Port is %d\n",inet_ntop(AF_INET,&addr_c.sin_addr,recip,ntohs(addr_c.sin_port)));
}
while(num)
{
for (int i = 0; i < SOCK_NUM; ++i) {
if (socketfd[i].fd <= 0)
continue;
int len = 0;
bzero(recbuf, sizeof(recbuf));
if (socketfd[i].revents & (POLLIN | POLLERR)) {
if ((len = read(socketfd[i].fd, recbuf, sizeof(recbuf))) < 0) {
//此处出现ECONNRESET可能是客户端给服务端发送Fin,服务端回ACK前客户端就GG了,此时ACK发出,客户端端口好已经被释放
//客户端收到ACK发现没有对于端口号会给回复一个RST复位
if (errno == ECONNRESET) {
close(socketfd[i].fd);
socketfd[i].fd = -1;
} else {
//凉了
exit(1);
}
} else if (0 == len) {
//断开连接
close(socketfd[i].fd);
socketfd[i].fd = -1;
} else {
printf("%s\n", recbuf);
write(socketfd[i].fd, recbuf, strlen(recbuf));
}
break;
}
}
num--;
}
}
close(socket_ser);
return 0;
}