epoll边缘触发_epoll边缘触发(epoll et) 源代码例子

/*

============================================================================

Name                : epoll_test.c

Author            :

Version         :

Copyright     : Your copyright notice

Description : epoll et example(echo) 此echo服务器对输入的内容复制了REPEAT_NUM(20000次),然后返回给客户端

用于测试epollout事件如何触发。

============================================================================

*/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define EPOLL_SIZE 10

#define EVENT_ARR 20

#define BACK_QUEUE 10

#define PORT 18001

#define BUF_SIZE 16

#define REPEAT_NUM 20000

#define OUT_BUF_SIZE 32*REPEAT_NUM

int g_srv_fd;

//由于有可能不能一次write所有的内容,所以需要全局变量保存内容的长度,内容输出到那里,

//在监听到epollout事件后继续上一次的发送

char g_out_buf[OUT_BUF_SIZE];//保存输出的内容

int g_out_buf_offset;                //保存输出到那里

int g_out_buf_len;                     //保存输出内容的长度

int g_has_write_buf;        //保存是否要写输出内容

void setnonblocking(int sockFd) {

int opt;

opt = fcntl(sockFd, F_GETFL);

if (opt < 0) {

printf("fcntl(F_GETFL) fail.");

exit(-1);

}

opt |= O_NONBLOCK;

if (fcntl(sockFd, F_SETFL, opt) < 0) {

printf("fcntl(F_SETFL) fail.");

exit(-1);

}

}

void handle_sig(int signum) {

close(g_srv_fd);

fprintf(stderr, "receiv sig int");

sleep(5);

exit(0);

}

int write_out_buf(int fd, char *out_buf,int buf_len,int offset)

{

int snd_len = write(fd, out_buf+offset, buf_len-offset);

int tmp_len;

if (snd_len==(buf_len-offset)){

do{

tmp_len = write(fd, out_buf+offset+snd_len, buf_len-offset-snd_len);

if (tmp_len>0 && tmp_len

snd_len += tmp_len;

break;

}

if(tmp_len == -1){

break;

}

snd_len += tmp_len;

}while(tmp_len>0);

}

if (((snd_len==-1||tmp_len==-1)    && errno ==EAGAIN) || snd_len

fprintf(stderr, "snd receiv eagin or snd_len

}

fprintf(stderr, "snd ret:%d\r\n", snd_len);

return snd_len;

}

//

void process_write(int fd, char *in_buf,int buf_len)

{

char *p_out_buf=g_out_buf;

int tmp_offset;

int i;

for(i=0; i

tmp_offset+=snprintf(p_out_buf+tmp_offset,OUT_BUF_SIZE-tmp_offset,"%d:%s\r\n", i,in_buf);

}

g_out_buf_len =tmp_offset;

g_out_buf_offset = 0;

g_has_write_buf = 0;

g_out_buf_offset +=write_out_buf(fd, g_out_buf, g_out_buf_len,g_out_buf_offset);

fprintf(stderr, "write_out_buf len:%d wret:%d\r\n", g_out_buf_len, g_out_buf_offset);

if (g_out_buf_offset

g_has_write_buf=1;

}

}

int main() {

int serverFd;

serverFd = socket(AF_INET, SOCK_STREAM, 0);

g_srv_fd = serverFd;

setnonblocking(serverFd);

signal(SIGPIPE, SIG_IGN);

signal(SIGINT, handle_sig);

int epFd = epoll_create(EPOLL_SIZE);

struct epoll_event ev, evs[EVENT_ARR];

ev.data.fd = serverFd;

ev.events = EPOLLIN | EPOLLET;

epoll_ctl(epFd, EPOLL_CTL_ADD, serverFd, &ev);

struct sockaddr_in serverAddr;

socklen_t serverLen = sizeof(struct sockaddr_in);

serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);

serverAddr.sin_port = htons(PORT);

if (bind(serverFd, (struct sockaddr *) &serverAddr, serverLen)) {

printf("bind() fail.\n");

exit(-1);

}

if (listen(serverFd, BACK_QUEUE)) {

printf("Listen fail.\n");

exit(-1);

}

int clientFd;

struct sockaddr_in clientAddr;

socklen_t clientLen;

char buf[BUF_SIZE];

int i = 0;

while (1) {

int nfds = epoll_wait(epFd, evs, EVENT_ARR, -1);

for (i = 0; i < nfds; i++) {

if (evs[i].data.fd == serverFd && (evs[i].events & EPOLLIN)) {

//epollet需要循环对监听的套接字accept,直到返回EAGAIN

do {

if ((clientFd = accept(serverFd,

(struct sockaddr *) &clientAddr, &clientLen)) < 0) {

printf("accept fail.\n");

break;

}

printf("Connect from %s:%d\n", inet_ntoa(clientAddr.sin_addr),

htons(clientAddr.sin_port));

setnonblocking(clientFd);

ev.data.fd = clientFd;

//注意,为了效率,这里直接对EPOLLIN,EPOLLOUT事件监听

ev.events = EPOLLIN | EPOLLET | EPOLLOUT;

//ev.events = EPOLLIN;

epoll_ctl(epFd, EPOLL_CTL_ADD, clientFd, &ev);

}while(clientFd>0);

} else if (evs[i].events & EPOLLIN) {

fprintf(stderr, "epollin event fd:%d\n", clientFd);

if ((clientFd = evs[i].data.fd) > 0) {

//epollet需要对套接字循环的读,直到len < BUF_SIZE,或者len<=0返回

int len = read(clientFd, buf, BUF_SIZE);

fprintf(stderr, "read fd:%d len:%d\n", clientFd, len);

if (len == BUF_SIZE) {

do {

/*

if (write(clientFd, buf, len) < 0) {

fprintf(stderr, "write fail!\n");

//break;

}

*/

process_write(clientFd, buf, len);

if (len < BUF_SIZE) {

fprintf(stderr, "len

BUF_SIZE);

break;

}

len = read(clientFd, buf, BUF_SIZE);

fprintf(stderr, "read2 fd:%d len:%d\n", clientFd, len);

} while (len > 0);

if (len == 0) {

epoll_ctl(epFd, EPOLL_CTL_DEL, clientFd, &ev);

close(clientFd);

evs[i].data.fd = -1;

fprintf(stderr, "close fd:%d\n", clientFd);

} else if (len == -1 && errno != EAGAIN) {

fprintf(stderr, " fd:%d\n", clientFd);

epoll_ctl(epFd, EPOLL_CTL_DEL, clientFd, &ev);

close(clientFd);

evs[i].data.fd = -1;

}

} else if (len > 0 && len < BUF_SIZE) {

process_write(clientFd, buf, len);

} else if (len == 0 || (len == -1 && errno != EAGAIN)) {

epoll_ctl(epFd, EPOLL_CTL_DEL, clientFd, &ev);

close(clientFd);

evs[i].data.fd = -1;

fprintf(stderr, "close fd:%d\n", clientFd);

}

}

} else if(evs[i].events & EPOLLOUT){

//监听到epollout时间,说明发送缓冲去可以写,那继续上一次的写操作

clientFd = evs[i].data.fd;

fprintf(stderr, "receive epoll out fd:%d\n", clientFd);

if(g_has_write_buf){

g_out_buf_offset +=write_out_buf(clientFd, g_out_buf, g_out_buf_len,g_out_buf_offset);

fprintf(stderr, "write len :%d writed:%d\n",g_out_buf_len,g_out_buf_offset);

if(g_out_buf_offset==g_out_buf_len){

g_has_write_buf = 0;

}

}

}else {

printf("other event.\n");

}

}

}

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值