一:原理
二:实现
和select差不多的逻辑
1、创建监听套接字,并开启监听
2、创建epoll
3、将监听套接字加入epoll
4、等待事件到来,
5、轮询监听事件队列,如果监听的事件的fd是服务器监听的socket,则将接入的客户端的socket fd加入epoll,不是则处理客户端的业务逻辑
6、下一轮监听
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <string.h>
#include <error.h>
#include <unistd.h>
int main(int argc, char **argv)
{
if (argc != 2)
{
return -1;
}
int port = atoi(argv[1]);
//第一步
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in serveraddr;
memset(&serveraddr, 0, sizeof(sockaddr_in));
serveraddr.sin_addr.s_addr = INADDR_ANY;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(port);
if (bind(sockfd, (sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
std::cout << "bind fail!" << std::endl;
return -1;
}
if (listen(sockfd, 10) < 0)
{
std::cout << "listen fail!" << std::endl;
return -2;
}
//第二步 epoll_create参数非0即可
int epfd = epoll_create(1);
std::cout << "epoll fd:" << epfd<<std::endl;
epoll_event ev, events[1024] = {0};
ev.events = EPOLLIN;
ev.data.fd = sockfd;
//第三步
if(epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev)==-1){
}
while (true)
{
//第三步,1024代表从epoll里面一次性最大拿1024个事件出来,-1代表一直等待
int needby = epoll_wait(epfd, events, 1024, -1);
std::cout << "epoll event count:" << needby;
for (int i = 0; i < needby; i++)
{
//第四步
if (events[i].data.fd == sockfd)
{
sockaddr_in client_addr;
memset(&client_addr, 0, sizeof(sockaddr_in));
socklen_t addlen = sizeof(sockaddr_in);
int client_fd = accept(sockfd, (sockaddr *)&client_addr, &addlen);
std::cout << "client fd:" << client_fd<<std::endl;
ev.events = EPOLLIN | EPOLLOUT;
ev.data.fd = client_fd;
epoll_ctl(epfd, EPOLL_CTL_ADD, client_fd, &ev);
}
else
{
int client_fd = events[i].data.fd;
//while(true){
char buff[1024] = {0};
int readlen = recv(client_fd, buff, sizeof(buff), 0);
std::cout << "readlen:" << readlen << std::endl;
std::cout << "buff:" << buff<<std::endl;
if (readlen == -1)
{
close(client_fd);
ev.events = EPOLLIN;
ev.data.fd = client_fd;
//记得将fd从 队列中移除
epoll_ctl(epfd,EPOLL_CTL_DEL,client_fd,&ev);
}else if(readlen == 0){
close(client_fd);
ev.events = EPOLLIN;
ev.data.fd = client_fd;
//记得将fd从 队列中移除
epoll_ctl(epfd,EPOLL_CTL_DEL,client_fd,&ev);
}else{
}
}
}
}
return 0;
}
一个链接数的测试