首先将套接字添加到 epoll 集以进行边缘触发读取:
epoll_event ev = {};
ev.data.fd = sock;
ev.events = EPOLLIN | EPOLLET; // edge triggered reading
epoll_ctl(efd, EPOLL_CTL_ADD, sock, &ev);
现在等待数据:
result = epoll_wait(efd, events, sizeEvents, timeoutMilliseconds);
假设,假设有 20+ 字节的数据可用。但随后的代码希望以 10 字节块的形式从流中解析消息:
result = recv(sock, buffer, 10, 0);
所以此时,您可能会说,“如果他调用epoll_wait
,他的代码可能会挂起或超时,即使套接字流中还有 10 个字节尚未读取。” 你是对的。
但是我的代码并没有返回到 epoll_wait,而是实际上切换了 epoll 标志,以便它可以在同一个套接字上发送回响应。
ev.data.fd = sock;
ev.events = EPOLLOUT|EPOLLET;
epoll_ctl(efd, EPOLL_CTL_MOD, sock, &ev);
请注意,不再设置 EPOLLIN。然后代码执行标准循环,send
直到epoll_wait
发送完整的响应。
设置消息响应后,代码将返回以边沿触发模式读取:
ev.data.fd = sock;
ev.events = EPOLLIN | EPOLLET;
epoll_ctl(efd, EPOLL_CTL_MOD, sock, &ev);
接着是等待:
result = epoll_wait(efd, events, sizeEvents, timeoutMilliseconds);
现在假设自上次从套接字读取后没有额外的数据到达,由于边缘级别没有改变sock
,上述挂起(或超时)吗?epoll_wait
或者 EPOLLIN 被关闭再打开的事实是否允许重置边缘状态,以便上述epoll_wait
调用将立即返回以指示套接字上可用的数据?