Sockets Epoll事件(EPOLLT)仅在udp套接字上触发一次
从在线资源中,他们说,如果epoll使用默认模式(级别触发器)侦听文件描述符,当fd(文件描述符)准备好读取且与fd相关的缓冲区数据未完全消耗时,epoll将继续触发,直到所有数据被消耗,然而,当我使用在udp套接字上侦听的epoll(LT模式)进行测试时,当出现多个字符时,epoll只触发一次。 过程如下: 步骤1:创建epoll、udp套接字fd,然后使epoll在套接字上侦听写事件 步骤2:向udp套接字发送多个字符(“abc”) 步骤3:每次触发epoll时,从udp套接字读取1个字符 我希望epoll触发三次,因为udp套接字接收3个字符,但结果是epoll只触发一次。 这是我的密码:Sockets Epoll事件(EPOLLT)仅在udp套接字上触发一次,sockets,udp,epoll,Sockets,Udp,Epoll,从在线资源中,他们说,如果epoll使用默认模式(级别触发器)侦听文件描述符,当fd(文件描述符)准备好读取且与fd相关的缓冲区数据未完全消耗时,epoll将继续触发,直到所有数据被消耗,然而,当我使用在udp套接字上侦听的epoll(LT模式)进行测试时,当出现多个字符时,epoll只触发一次。 过程如下: 步骤1:创建epoll、udp套接字fd,然后使epoll在套接字上侦听写事件 步骤2:向udp套接字发送多个字符(“abc”) 步骤3:每次触发epoll时,从udp套接字读取1个字符
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/errno.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define BUFFER_SIZE 512
#define log(fmt, arg...) printf(""fmt, ##arg)
void main(){
int fd1,efd, fds, i, fd;
int ret, addr_len;
struct epoll_event g_event;
struct epoll_event *epoll_events_ptr;
char buffer[BUFFER_SIZE] = {0};
struct sockaddr_in addr1;
fd1 = socket(AF_INET, SOCK_DGRAM, 0);
if (fd1 == -1) {
log("create socket fail \r\n");
return ;
}
addr1.sin_family = AF_INET;
addr1.sin_addr.s_addr = INADDR_ANY;
addr1.sin_port = htons(3500);
addr_len = sizeof(struct sockaddr_in);
if (0 != bind(fd1, (struct sockaddr *)&addr1, sizeof(struct sockaddr_in))) {
log("bind local listening addr fail,errno : %d \r\n", errno);
goto err;
}
efd = epoll_create1(0);
if (efd == -1) {
log("create epoll fail \r\n");
goto err;
}
log("create epoll instance success \r\n");
epoll_events_ptr = (struct epoll_event *)calloc(2, sizeof(struct epoll_event));
if (epoll_events_ptr == NULL) {
log("calloc fail \r\n");
goto err;
}
g_event.data.fd = fd1;
g_event.events = EPOLLIN;
epoll_ctl(efd, EPOLL_CTL_ADD, fd1, &g_event);
while(1) {
fds = epoll_wait(efd, epoll_events_ptr, 2, -1);
for (i = 0; i<fds; i++)
{
if (epoll_events_ptr[i].events & EPOLLIN)
{
ret = recv(fd1, buffer, 1, MSG_DONTWAIT);
if(ret != -1)
log("recv msg : %s \n", buffer);
}
memset(buffer, 0, BUFFER_SIZE);
}
}
err:
close(fd1);
if(epoll_events_ptr)
free(epoll_events_ptr);
return ;
}
#包括
#包括
#包括
#包括
#包括您将UDP视为流协议,即TCP。事实并非如此。这是一个数据报协议。如果将UDP数据报读入太小而无法接收的缓冲区,则会丢弃该数据报的其余部分。下次不会留在缓冲区中
因此,在UDP中,一次读取一个字符是毫无意义的,更不用说在任何协议中效率极低
注意:您不需要memset()
,并且:
log("recv msg : %s \n", buffer);
这是无效的。应该是:
log("recv msg : %.*s \n", ret, buffer);
您不能假设接收到的数据以null结尾。我还测试了在STDIN_文件上侦听epoll(LT模式)否,所有过程都是相同的,除了文件描述符,一个用于udp套接字,一个用于标准输入,但结果是,在侦听STDIN时,epoll将触发数次,而在udp套接字上仅触发一次,udp套接字上有什么特殊的功能吗?感谢@EJP的回答,根据您的想法,我做了另一个测试(udp套接字准备好读取后,每次读取1个字符),结果显示读取1个字符后,读取操作被阻止,正如您所说的“数据报的其余部分被丢弃”,这解释了为什么epoll只触发一次。顺便说一下,感谢您指出日志(“recv msg:%s\n”,buffer);