他们从在线资源中得知,如果epoll使用默认模式(级别触发器)监听文件描述符,则当fd(文件描述符)准备好读取且与fd相关联的缓冲区数据未完全使用时,epoll将继续触发直到所有数据被消耗,但是,当我在udp套接字上使用epoll(LT模式)进行测试时,当出现多个字符时,epoll仅触发一次。 流程如下:
步骤1:创建epoll,udp套接字fd,然后使epoll监听套接字上的写事件。
步骤2:将多个字符(“ abc”)发送到udp套接字
第3步:每次epoll触发,然后从udp套接字读取1个字符。
我期望epoll触发3次,因为udp套接字接收3个字符,但是结果是epoll仅触发一次。 这是我的代码:
#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 ;
}
答案 0 :(得分:0)
您正在将UDP视为一种流协议,即TCP。不是。这是一个数据报协议。如果您将UDP数据报读入一个太小而无法接收的缓冲区,则该数据报的其余部分将被丢弃。下次不会再留在缓冲区中了。
因此,在UDP中一次读取一个字符毫无意义,更不用说在任何协议中效率都非常低了。
NB您不需要memset()
,并且这样:
log("recv msg : %s \n", buffer);
无效。应该是:
log("recv msg : %.*s \n", ret, buffer);
您不能假定接收到的数据以空值结尾。