#include<netinet/in.h>
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include <sys/epoll.h>
#define PORT 8888
#define SIZE 2048
int main()
{
int socketser,sockclient;
int listenfd[SIZE];
int treefd;
char bufrec[1024];
struct sockaddr_in addr,clientaddr;
struct epoll_event tmp,epolle[SIZE];
memset(listenfd,-1,sizeof(listenfd));
socketser=socket(AF_INET,SOCK_STREAM,0);
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(socketser,(struct sockaddr*)&addr,sizeof(addr));
listen(socketser,20);
treefd = epoll_create(SIZE);
tmp.events = EPOLLIN;
tmp.data.fd = socketser;
epoll_ctl(treefd,EPOLL_CTL_ADD,socketser,&tmp);
int ret;
while(1)
{
ret = epoll_wait(treefd,epolle,SIZE,-1);
for(int n=0;n<ret;n++)
{
if(!epolle[n].events & EPOLLIN)
continue;
if(epolle[n].data.fd == socketser)
{
int i =0;
for(i =0;i<SIZE;i++)
{if(listenfd[i]<0) {
break;
}
}
int length = sizeof(clientaddr);
listenfd[i] = accept(socketser,(struct sockaddr*)&clientaddr,(socklen_t*)&length);
tmp.events = EPOLLIN;
tmp.data.fd = listenfd[i];
epoll_ctl(treefd,EPOLL_CTL_ADD,listenfd[i],&tmp);
}
else
{
memset(bufrec,0,sizeof(bufrec));
sockclient = epolle[n].data.fd;
int length = read(sockclient,bufrec,1024);
if(length == 0)
{
for(int i = 0;i<SIZE;i++)
{
if(listenfd[i] == sockclient )
{
epoll_ctl(treefd,EPOLL_CTL_DEL,listenfd[i],NULL);
close(sockclient);
listenfd[i]=-1;
break;
}
}
}
else
{
write(sockclient,bufrec,length);
}
}
}
}
close(treefd);
close(socketser);
}
多路io epoll模型与poll有很多相似之处,重点是三个函数epoll_create、epoll_ctl、epoll_wait ,注意的是epoll_event中data字段我们设置fd为要监听的fd,这样当有响应的时候我们就能获得具体的fd。epoll_create采用的是红黑树插入速度比数组快的多,有兴趣的可以去看看平衡二叉树,后续有时间我会写一些数据结构