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;
}

时间: 2024-10-23 04:55:29

epoll 的两种用法的相关文章

JSP中的include的两种用法

1.两种用法 <@inlcude file ="header.jsp"/> 此时引入的是静态的jsp文件,它将引入的jsp中的源代码原封不动地附加到当前文件中,所以在jsp程序中使用这个指令的时候file里面的值(即要导入的文件)不能带多余的标签或是与当前jsp文件重复的东西.例如里面不要包含<html><body>这样的标签,因为是把源代码原封不动的附加过来,所以会与当前的jsp中的这样的标签重复导致出错. <jsp:include page

epoll的两种触发模式

epoll有两种模式,Edge Triggered(简称ET) 和 Level Triggered(简称LT).在采用这两种模式时要注意的是,如果采用ET模式,那么仅当状态发生变化时才会通知,而采用LT模式类似于原来的select/poll操作,只要还有没有处理的事件就会一直通知. 以代码来说明问题: 首先给出server的代码,需要说明的是每次accept的连接,加入可读集的时候采用的都是ET模式,而且接收缓冲区是5字节的,也就是每次只接收5字节的数据: Java代码   #include <

Android---24---Spinner的两种用法

Spinner是一个列表选择框,它有两种用法: 一种是使用android:entries属性的,一种是不使用该属性,通过动态的添加Adapter来实现的. 第一种: MainActivity.java: import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import andr

operator 的两种用法

C++,有时它的确是个耐玩的东东,就比如operator,它有两种用法,一种是operator overloading(操作符重载),一种是operator casting(操作隐式转换). 1.操作符重载C++可以通过operator实现重载操作符,格式如下:类型T operator 操作符 (),比如重载+,比如下面这个例子template<typename T> class A{public:     const T operator+(const T& rhs)     {  

jsp中include的两种用法

JSP中的include的两种用法 1.两种用法 <%@ include file=” ”%> <jsp:include page=” ” flush=”true”/> 2.用法区别 (1)执行时间上区别 <%@ include file=”relativeURI”%>                   是在翻译阶段执行 <jsp:include page=”relativeURI” flush=”true” />  在请求处理阶段执行. (2)引入内容的

epoll的两种工作模式

epoll有两种模式,Edge Triggered(简称ET) 和 Level Triggered(简称LT).在采用这两种模式时要注意的是,如果采用ET模式,那么仅当状态发生变化时才会通知,而采用LT模式类似于原来的select/poll操作,只要还有没有处理的事件就会一直通知. 以代码来说明问题: 首先给出server的代码,需要说明的是每次accept的连接,加入可读集的时候采用的都是ET模式,而且接收缓冲区是5字节的,也就是每次只接收5字节的数据: Java代码   #include <

c++ operator操作符的两种用法:重载和隐式类型转换,string转其他基本数据类型的简洁实现string_cast

C++中的operator主要有两个作用,一是操作符的重载,一是自定义对象类型的隐式转换.对于操作符的重载,许多人都不陌生,但是估计不少人都不太熟悉operator的第二种用法,即自定义对象类型的隐式转换,我们下面就用以下这个小例子温故一下这两种用法: 1 #include <iostream> 2 #include <sstream> 3 using namespace std; 4 5 class FuncObj 6 { 7 public: 8 FuncObj(int n):

include的两种用法之间的区别

以下是对include 两种用法的区别 主要有两个方面的不同; 一:执行时间上: <%@ include file="relativeURI"%> 是在翻译阶段执行 <jsp:include page="relativeURI" flush="true" /> 在请求处理阶段执行. 二:引入内容的不同: <%@ include file="relativeURI"%> 引入静态文本(html

夺命雷公狗C/C++-----5---include的两种用法

我们的include是有两种用法的,如: 上面这种就是在头文件方式进行引入的,  include  <>  括号的是包含系统文件的.... 还有一种,比如我首先写个头文件先,如下所示: 然后我们在愿文件里面进行引入,如下所示: 这样也是成功的引入了... 总结   include 的区别 #include <>  包含系统的文件 #include "":  包含总结编写的文件