gpt4 book ai didi

linux - EBADF while recv after epoll_wait

转载 作者:IT王子 更新时间:2023-10-29 01:03:36 24 4
gpt4 key购买 nike

我遇到了以下问题:我有一个接收连接的 epoll 代码:

while (1) {
int nfds = epoll_wait(epollfd, events, 4096, -1);
if (nfds == -1) {
if (errno == EINTR)
continue;
perror("epoll_wait");
exit(EXIT_FAILURE);
}

for (int i = 0; i < nfds; i++) {
if (events[i].data.fd == server_sock) {
client_sock = accept(server_sock,
(struct sockaddr *)&client_name,
(socklen_t *)(&client_name_len));

if (client_sock == -1) //server overloaded
continue;

ev.events = EPOLLIN | EPOLLERR;

#ifdef CORE_NONBLOCKING_SOCKETS
Arch::set_nonblocking(client_sock);
ev.events |= EPOLLET; //input data and connection closing
#endif


#ifdef EPOLLRDHUP
ev.events |= EPOLLRDHUP ;//
#else
//for old libraries
ev.events |= EPOLLHUP;//
#endif

ev.data.fd = client_sock;

if (epoll_ctl(epollfd, EPOLL_CTL_ADD, client_sock, &ev) == -1) {
perror("epoll_ctl: client_socket");
exit(EXIT_FAILURE);
}

accept_request(client_sock);

} else {

#ifdef EPOLLRDHUP
if (events[i].events & EPOLLRDHUP) {
std::cout << "EPOLLRDHUP on " << events[i].data.fd << std::endl;
listener->disconnectDriver(events[i].data.fd);
}
#else
if (events[i].events & EPOLLHUP) {
std::cout << "EPOLLHUP on " << events[i].data.fd << std::endl;
listener->disconnectDriver(events[i].data.fd);
}
#endif
if (events[i].events & EPOLLIN) {
std::cout << "debug EPOLLIN on " << events[i].data.fd << std::endl;
accept_request(events[i].data.fd);
}

if (events[i].events & EPOLLERR) {
std::cout << "debug EPOLLERR on " << events[i].data.fd << std::endl;
listener->disconnectDriver(events[i].data.fd);
}


}
}

当我收到输入连接时,我试图读取所有 buff 数据:

void get_all_buf(int sock, std::string & inStr) {
int n = 1;
int total = 0;

char c;
char temp[1024*1024];

bzero(temp, sizeof(temp));

do {
#ifdef CORE_NONBLOCKING_SOCKETS
timespec time_to_wait;
time_to_wait.tv_nsec = 10000000;
time_to_wait.tv_sec = 0;
timespec tm;

time_t begin = time(NULL);
do {
#endif

n = recv(sock, &temp[total], sizeof(temp), 0);

#ifdef CORE_NONBLOCKING_SOCKETS
nanosleep(&time_to_wait, &tm);
time_t end = time(NULL);
if ((end - begin) > MAX_CLIENT_TIME) {
inStr = std::string();
return;
}
} while (n < 0 && errno == EAGAIN); //nonblocking sockets in edge-triggered mode
#endif

if (n > 0) {
total += n;
} else if (n == 0) {
//TODO: error handling
//debug
std::cout << "possibly no one byte was received" << std::endl;
break;
} else if (n < 0) {
//TODO: error handling
//debug
std::cout << "error while receiving data" << std::endl;
if (errno == EBADF) {
std::cout << "recv returns with EBADF: " << strerror(errno) << std::endl;
} else if (errno == EFAULT) {
std::cout << "recv returns with EFAULT: " << strerror(errno) << std::endl;
} else if (errno == EINTR) {
std::cout << "recv returns with EINTR: " << strerror(errno) << std::endl;
} else if (errno == EINVAL) {
std::cout << "recv returns with EINVAL: " << strerror(errno) << std::endl;
}
//end debug
break;
}

} while (!strstr(temp, "</packet>"));
inStr = temp;
};

accept_request 函数中。但有时我的调试输出如下:

packet type='connect'
size of vector<Driver> in getDriversWithMoney is 1
epoll_wait detected activity of 164 counter i = 0 nfds = 1
EPOLLRDHUP on 164
disconnectDriver (fd = 164)
driver 1 disconnected
debug EPOLLIN on 164
error while receiving data
recv returns with EBADF: Invalid file descriptor

这意味着某人首先连接而不是断开连接,当他尝试再次连接时 recv 返回 EBADF。我做错了什么?请帮助我。

P.S. EPOLLRDHUP 我只是关闭文件描述符。 epoll man 说没问题,因为 epoll 自己从 epoll_wait 队列中移除关闭的 fd。

最佳答案

当远程主机关闭套接字时,epoll() 报告文件描述符的 HUPEPOLLIN

首先检查EPOLLRDHUP,然后关闭套接字;然后检查 EPOLLIN,也找到它,然后尝试调用 recv()。由于套接字已关闭,文件描述符不再有效,您将得到 EBADF(已关闭的套接字已从 epoll 集合中移除,所以后续 epoll_wait() 调用不会返回它;但是对于已经返回的 epoll_wait() 来说为时已晚 - EPOLLIN已经在您的 events[i] 中等待。

您需要在调用 disconnectDriver() 后停止检查事件(如果它关闭了文件描述符):

        if (events[i].events & EPOLLRDHUP) {
std::cout << "EPOLLRDHUP on " << events[i].data.fd << std::endl;
listener->disconnectDriver(events[i].data.fd);
continue;
}

关于linux - EBADF while recv after epoll_wait,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4895581/

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