首页 > 代码库 > epoll 的两种用法

epoll 的两种用法

struct epoll_event 的data成员是一个union类型

里面要么就是fd,要么就是ptr

最好不要一会用ptr一会用fd

最好坚持从头到尾的使用一个

 

 

第一种只是使用epoll_event.data.fd

#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/epoll.h>

#include <iostream>
using namespace std;

int non_block(int fd){
int flag;
flag = fcntl(fd,F_GETFL);
flag =flag | O_NONBLOCK;
return fcntl(fd,F_SETFL,flag);
}


int main(){
const int epoll_max = 10000;
const int buf_size = 1000;
char buf[buf_size];
struct epoll_event ev;
struct epoll_event events[epoll_max];
int sock_fd;
struct sockaddr_in server,client;
socklen_t len;
int ret;
int epoll_fd;
int num_fd;
int client_fd;
int size;
int fd;


len = sizeof(struct sockaddr);
sock_fd = socket(AF_INET,SOCK_STREAM,0);
if(sock_fd < 0){
cerr <<"socket error"<<endl;
return 1;
}
server.sin_family = AF_INET;
server.sin_port = htons(1987);
server.sin_addr.s_addr = htonl(INADDR_ANY);

int opt;
opt = 1;
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));


ret = bind(sock_fd,(struct sockaddr*)&server,len);
if(ret < 0){
cerr <<"bind error"<<endl;
return 1;
}

ret = non_block(sock_fd);
if(ret < 0){
cerr <<"fcntl error"<<endl;
return 1;
}

ret = listen(sock_fd,10);
if(ret < 0){
cerr <<"listen error"<< endl;
return 1;
}

epoll_fd = epoll_create(epoll_max);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = sock_fd;
epoll_ctl(epoll_fd,EPOLL_CTL_ADD,sock_fd,&ev);

while(1){
num_fd = epoll_wait(epoll_fd,events,epoll_max-1,-1);
for(int i = 0;i < num_fd;i ++){
if(events[i].data.fd == sock_fd){
client_fd = accept(sock_fd,(struct sockaddr*)&client,&len);
if(client_fd == -1){
cerr <<"accept error"<<endl;
continue;
}
printf("new client ip=%s port=%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
ev.data.fd = client_fd;
ev.events = EPOLLIN | EPOLLET;
epoll_ctl(epoll_fd,EPOLL_CTL_ADD,client_fd,&ev);
}else if(events[i].events & EPOLLIN){
client_fd = events[i].data.fd;
size = read(client_fd,buf,buf_size);
printf("read from client data is\n");
fd = open(buf,O_RDONLY);
while((size = read(fd,buf,buf_size))>0){
write(client_fd,buf,size);
}
write(STDOUT_FILENO,buf,size);
memset(buf,0,buf_size);
}else{
write(events[i].data.fd,"fuck you",8);
}

}

}
return 0;
}

 

 

第二种只是使用epoll_event.data.ptr

#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#include <netinet/in.h>

void non_block(int fd){
fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0)|O_NONBLOCK);
}

struct node{
int fd;
char *buf;
int len;
};

typedef struct node node;


int main(){
printf("start\n");
int epoll_max=100;
int epoll_num;
struct epoll_event ev,evs[epoll_max];
node *x;
int server_fd,client_fd,epoll_fd;
struct sockaddr_in server_addr,client_addr;
socklen_t len;
int num;
int l;
int i;
char buf_len = 100;
char buf[buf_len];

server_addr.sin_port = htons(1987);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

server_fd = socket(AF_INET,SOCK_STREAM,0);
if(server_fd <0){
perror(strerror(errno));
}
len = sizeof(struct sockaddr);
if(bind(server_fd,(struct sockaddr*)&server_addr,len)<0)
perror(strerror(errno));
non_block(server_fd);
if(listen(server_fd,10)<0)
perror(strerror(errno));
epoll_fd = epoll_create(epoll_max);
if(epoll_fd <0)
perror(strerror(errno));
x = (node*)malloc(sizeof(node));
x->fd = server_fd;
x->buf = (char*)malloc(10);
x->len = 10;
ev.data.ptr = x;
ev.events = EPOLLIN|EPOLLET;
epoll_ctl(epoll_fd,EPOLL_CTL_ADD,server_fd,&ev);
for(i = 0;i < epoll_max;i ++){
evs[i].data.ptr = NULL;
}
num = 0;
printf("process\n");
while(1){
printf("num is %d\n",num);
sleep(1);
printf("sleep 1 second\n");
if(num >10){
for(i = 0;i < epoll_max;i ++){
x = (node*)(evs[i].data.ptr);
if(x != NULL){
free(x->buf);
}
free(x);
}
}
epoll_num = epoll_wait(epoll_fd,evs,epoll_max,-1);
for(i = 0;i < epoll_num;i ++){
x = evs[i].data.ptr;
if(x->fd == server_fd){
client_fd = accept(server_fd,(struct sockaddr*)&client_addr,&len);
num ++;
x = malloc(sizeof(node));
x->fd = client_fd;
x->buf = (char*)malloc(10);
strcpy(x->buf,"chengying");
x->len = 10;
ev.events = EPOLLIN|EPOLLOUT;
ev.data.ptr = x;
non_block(client_fd);
epoll_ctl(epoll_fd,EPOLL_CTL_ADD,client_fd,&ev);
}else if(evs[i].events & EPOLLIN){
x = (node*)(evs[i].data.ptr);
l = read(x->fd,buf,buf_len);
write(STDOUT_FILENO,buf,l);
write(x->fd,buf,l);
memset(buf,0,buf_len);
}
}


}


return 0;
}

epoll 的两种用法