У меня следующая проблема: у меня есть код 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);
}
}
}
когда я получил входное соединение, я пытаюсь прочитать все данные баффов:
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. on EPOLLRDHUP
Я просто закрываю файловый дескриптор. epoll
мужчина говорит, что все в порядке, потому что epoll
самостоятельно удаляет закрытый файл из очереди epoll_wait
.