首先,将一个套接字添加到 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
调用将立即返回,指示套接字上有可用的数据?
EPOLLOUT
并写入响应的原因。 - undefined