epoll的ET非阻塞模式

readn调用的阻塞,比如设定读500个字符,但是只读到498,完事儿阻塞了,等另剩下的2个字符,然而在server代码里,一旦read变为readn阻塞了,它就不会被唤醒了,因为epoll_wait因为readn的阻塞不会循环执行,读不到新数据。有点死锁的意思,差俩字符所以阻塞,因为阻塞,读不到新字符。

LT(level triggered):LT是缺省的工作方式,并且同时支持block和no-block socket。在这种做法中,内核告诉你一个文件描述符是否就绪了,然后你可以对这个就绪的fd进行IO操作。如果你不作任何操作,内核还是会继续通知你的,所以,这种模式编程出错误可能性要小一点。传统的select/poll都是这种模型的代表。
ET(edge-triggered):ET是高速工作方式,只支持no-block socket。在这种模式下,当描述符从未就绪变为就绪时,内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知。请注意,如果一直不对这个fd作IO操作(从而导致它再次变成未就绪),内核不会发送更多的通知(only once).

1.#include <stdio.h>  
2.#include <string.h>  
3.#include <netinet/in.h>  
4.#include <arpa/inet.h>  
5.#include <sys/wait.h>  
6.#include <sys/types.h>  
7.#include <sys/epoll.h>  
8.#include <unistd.h>  
9.#include <fcntl.h>  
10.  
11.#define MAXLINE 10  
12.#define SERV_PORT 8000  
13.  
14.int main(void)  
15.{  
16.    struct sockaddr_in servaddr, cliaddr;  
17.    socklen_t cliaddr_len;  
18.    int listenfd, connfd;  
19.    char buf[MAXLINE];  
20.    char str[INET_ADDRSTRLEN];  
21.    int efd, flag;  
22.  
23.    listenfd = socket(AF_INET, SOCK_STREAM, 0);  
24.  
25.    bzero(&servaddr, sizeof(servaddr));  
26.    servaddr.sin_family = AF_INET;  
27.    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);  
28.    servaddr.sin_port = htons(SERV_PORT);  
29.  
30.    bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));  
31.  
32.    listen(listenfd, 20);  
33.  
34.    ///  
35.    struct epoll_event event;  
36.    struct epoll_event res_event[10];  
37.    int res, len;  
38.  
39.    efd = epoll_create(10);  
40.  
41.    event.events = EPOLLIN | EPOLLET;     /* ET 边沿触发,默认是水平触发 */  
42.  
43.    //event.events = EPOLLIN;  
44.    printf("Accepting connections ...\n");  
45.    cliaddr_len = sizeof(cliaddr);  
46.    connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);  
47.    printf("received from %s at PORT %d\n",  
48.            inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),  
49.            ntohs(cliaddr.sin_port));  
50.  
51.    flag = fcntl(connfd, F_GETFL);          /* 修改connfd为非阻塞读 */  
52.    flag |= O_NONBLOCK;  
53.    fcntl(connfd, F_SETFL, flag);  
54.  
55.    event.data.fd = connfd;  
56.    epoll_ctl(efd, EPOLL_CTL_ADD, connfd, &event);      //将connfd加入监听红黑树  
57.    while (1) {  
58.        printf("epoll_wait begin\n");  
59.        res = epoll_wait(efd, res_event, 10, -1);        //最多10个, 阻塞监听  
60.        printf("epoll_wait end res %d\n", res);  
61.  
62.        if (res_event[0].data.fd == connfd) {  
63.            while ((len = read(connfd, buf, MAXLINE/2)) >0 )    //非阻塞读, 轮询  
64.                write(STDOUT_FILENO, buf, len);  
65.        }  
66.    }  
67.  
68.    return 0;  
69.}  

多了这几行:
在这里插入图片描述

epoll 的 ET模式, 高效模式,但是只支持 非阻塞模式。 — 忙轮询。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值