unix网络编程_【Unix网络编程】epoll的非阻塞IO

epoll的两种工作模式:ET(边缘触发)和LT(持续触发)

代码

struct epoll_event event;
event.events = EPOLLIN | EPOLLET;

监听事件默认是LT模式,因此如果要设置为ET模式,需要手动设置epoll_event.events

从头说起

我们知道,将监听事件委托给内核之后,内核会维护一个缓冲区用来从另一头的套接字中读取数据;在服务器端的代码中可以通过read来读这个缓冲区。

在ET模式下,epoll_wait仅在有连接到达时才返回,我们来看看,下面是主工作循环。这里专门将read的字节数设置为MAXLINE/2,即每次只读取缓冲区保存数据的一半。按照ET模式,我们只能读到缓冲区的前MAXLINE/2个数据,而后面的一半则无法读取。[ps:MAXLINE=10]

    while (1) {
        epoll_wait(efd, res_event, 10, -1);
        if (res_event[0].data.fd == conn_fd)
        {
            len = read(conn_fd, buf, MAXLINE / 2);
            write(STDOUT_FILENO, buf, len);
        }
    }

启动server,并连接一个client,

18ea91fe677f29623b876793e48344bf.png

让client输入1234567890[10个数据],

5cd08c2f573ceaba1c0375c1fc31f0fe.png

我们观察服务器端的输出,

928c51114b4734699f336948a81d47fe.png

可见,这次读取只读到了一半的数据,并且server再次阻塞到epoll_wat。

现在,把epoll_wait的模式设置为LT模式,然后在做同样的事情,

84d502330da461b040046b82a1e70fe1.png

可见,epoll_wait对一次client的输入返回了两次。

非阻塞IO

当然,我们希望每次都能完整的获得client的传输的数据,但这意为着只能使用LT模式吗?这就要引入epoll的非阻塞IO模式,它需要配合

  1. 对连接的套接字(accpet返回的)的读操作设置为非阻塞模式文件
  2. 对内核缓冲区进行轮询read操作

首先,我们先尝试只做2而不做1,即在一次epoll_wait返回后对缓冲区轮询而不将连接的套接字设置为非阻塞。

    while (1) {
        res = epoll_wait(efd, res_event, 10, -1);
        printf("wait res = %dn", res);
        if (res_event[0].data.fd == conn_fd)
            while ((len = read(conn_fd, buf, MAXLINE/2)) > 0)
                write(STDOUT_FILENO, buf, len);
    }

这时的效果

8b8c5c0e4ae48a0219a5f93de91ca43e.png

可以看到直接读出了缓冲区所有的数据,并且阻塞了。但是注意,此时server是阻塞在了read上而非epoll_wait,因此无法对别的client响应。我们可以通过gdb调试发现这一点

1ac07af5cacd97e06f60d854e5519b21.png

在写完最有一个数据后,进程阻塞在read上。如果此时有别的client访问server,那么就会死锁。

鉴于此,需要将建立连接的套接字文件设置为非阻塞模式

int fd_flag = fcntl(conn_fd, F_GETFL);
fd_flag |= O_NONBLOCK;
fcntl(conn_fd, F_SETFL, fd_flag);

这样,当client传输完毕后,read就可以返回,继续进行epoll_wait。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值