gpt4 book ai didi

c - Linux 异步 epoll() 服务器在 EPOLLRDHUP 发生时出现问题

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:33:14 26 4
gpt4 key购买 nike

我正在尝试在 Linux 中使用 epoll() 创建一个异步 Web 服务器,但是每当事件 EPOLLRDHUP 发生时就会出现问题。当标志 EPOLLONESHOT 未设置时,服务器会在循环期间多次尝试处理无用事件(不是 EPOLLIN 或 EPOLLOUT)而不停止,这会导致服务器完全无响应(并需要重新启动)。当设置标志 EPOLLONESHOT 时,服务器会在短时间(秒)内变得无响应,然后再次响应(这仍然不理想)。我不确定是什么原因造成的,因为每当 EPOLLRDHUP 发生时我都会关闭套接字。这是我的代码:

int server_fd, new_socket; 
long valRead;
struct sockaddr_in address;
int addrlen = sizeof(address);

//setup code (bind(), etc.) would be here

struct connection {
int socket;
unsigned int connectionType;
void* dataToSend;
unsigned int dataByteSize;
struct epoll_event event;
bool active;
};

struct connection* connections = (struct connection*)malloc(1000 * sizeof(struct connection));
connections[0].socket = server_fd;
connections[0].connectionType = 1U;
connections[0].event.events = EPOLLIN;
connections[0].event.data.ptr = &connections[0];

unsigned int connectionIndex = 1U;

fcntl(server_fd, F_SETFL, O_NONBLOCK);

int epollFd = epoll_create(10);
epoll_ctl(epollFd, EPOLL_CTL_ADD, server_fd, &connections[0].event);

struct epoll_event* receivedEvents = malloc(sizeof(struct epoll_event) * 1000);
struct connection currentConnection;

#define MAX_EVENTS 10
int numEventsReady;
unsigned int eventIndex;
while (1) {
printText("\n+++++++ Waiting for new connection ++++++++\n\n", 46);

numEventsReady = epoll_wait(epollFd, receivedEvents, MAX_EVENTS, -1);
if (numEventsReady == -1) {
printf("\nErrno:");
printf("%i", errno);
printf("\n");
fprintf(stderr, "epoll_wait() failed: %s\n", strerror(errno));
exit(7);
}
eventIndex = 0U;
while (eventIndex < numEventsReady) {
currentConnection = *((struct connection*)receivedEvents[eventIndex].data.ptr);
switch (currentConnection.connectionType) {
case 1U:
//printText("\nConnected", 10);
new_socket = accept4(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC);
if (new_socket != -1) {
connections[connectionIndex].socket = new_socket;
connections[connectionIndex].connectionType = 2U;
connections[connectionIndex].event.events = EPOLLIN | EPOLLRDHUP;
connections[connectionIndex].event.data.ptr = &connections[connectionIndex];

epoll_ctl(epollFd, EPOLL_CTL_ADD, new_socket, &connections[connectionIndex].event);

++connectionIndex;
}
break;
case 2U:
if (receivedEvents[eventIndex].events & EPOLLERR) {
printf("\nEPOLLERR\n");
close(currentConnection.socket);
}
else if(receivedEvents[eventIndex].events & EPOLLHUP) {
printf("\nEPOLLHUP\n");
close(currentConnection.socket);
}
else if(receivedEvents[eventIndex].events & EPOLLRDHUP) {
printf("\nEPOLLRDHUP\n");
close(currentConnection.socket);
}
else if (receivedEvents[eventIndex].events & EPOLLIN) {
valRead = recv(currentConnection.socket, buffer, 65536, 0);
if (valRead < 1) {
printf("recv error");
if (errno != EAGAIN && errno != EWOULDBLOCK) {
printf("errno != EAGAIN && errno != EWOULDBLOCK");
close(currentConnection.socket);
}
break;
}
printText(buffer, valRead);

currentConnection.event.events = EPOLLOUT | EPOLLRDHUP;
currentConnection.event.data.ptr = &currentConnection;
epoll_ctl(epollFd, EPOLL_CTL_MOD, currentConnection.socket, &currentConnection.event);

if (buffer[0] == 'G' && buffer[1] == 'E' && buffer[2] == 'T') {
switch (buffer[5]) {
case ' ': //default web page (index.htm)
currentConnection.dataToSend = indexHtm;
currentConnection.dataByteSize = sizeof(indexHtm);
//sendSocketData(new_socket, indexHtm, sizeof(indexHtm));
break;
}
}
else if (receivedEvents[eventIndex].events & EPOLLOUT) {
valRead = send(currentConnection.socket, currentConnection.dataToSend, currentConnection.dataByteSize, 0);
if (valRead == -1) {
printf("send error has ocurred\n");
if (errno != EAGAIN && errno != EWOULDBLOCK) {
printf("\nerrno != EAGAIN && errno != EWOULDBLOCK\n");
close(currentConnection.socket);
}
break;
}

currentConnection.event.events = EPOLLIN | EPOLLRDHUP;
currentConnection.event.data.ptr = &currentConnection;
valRead = epoll_ctl(epollFd, EPOLL_CTL_MOD, currentConnection.socket, &currentConnection.event);
}
break;
}
++eventIndex;
}
}

最佳答案

这里你使用了两次的这个模式是错误的:

currentConnection.event.data.ptr = &currentConnection;
valRead = epoll_ctl(epollFd, EPOLL_CTL_MOD,
currentConnection.socket, &currentConnection.event);

您正在将 data.ptr 设置为您的局部变量 currentConnection(它一直被重用和覆盖),而它确实应该指向您的连接数组!

据我所知,currentConnection应该是一个指针类型:

struct connection *currentConnection;

你代码后面的赋值应该是这样的

currentConnection = (struct connection*)receivedEvents[eventIndex].data.ptr;

当然,您必须修复结构成员访问以及 data.ptr 的设置,就像您在此处所做的那样:

currentConnection.event.data.ptr = &currentConnection;

根本没有必要。

关于c - Linux 异步 epoll() 服务器在 EPOLLRDHUP 发生时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54014453/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com