Я пишу простой TCP-сервер для передачи файлов.Сервер использует объекты epoll для мониторинга входящих соединений и данных, и я хотел бы использовать метод sendfile()
, чтобы обеспечить более быструю передачу файлов.
Попытка использовать sendfile()
для fd, возвращенного epoll_wait()
приводит к ошибке 29.
Я могу читать с этого fd с помощью традиционного read()
метода, что означает, что fd не поврежден (хотя fstat()
на fd возвращает размер 0).
Я прилагаю фрагмент кода только sendfile()
, при необходимости могу поделиться всем кодом:
epoll_wait:
while (true) {
int activeFds = epoll_wait(epollfd, events, MAXEVENTS, -1);
if (-1 == activeFds) {
printf("Epoll wait failed %s\n", strerror(errno));
res = false;
goto Exit;
}
res = iterateActiveFds(activeFds, events);
if (false == res) {
goto Exit;
}
}
Найти fd:
bool iterateActiveFds(int activeFds, struct epoll_event events[]) {
bool res = true;
int i;
for (i = 0; i < activeFds; ++i) {
if (events[i].data.ptr == &sockFd) {
res = acceptNewConnection(i);
} else {
res = handelIncomingData(i);
}
}
return res;
}
Дескриптор подключения:
bool handelIncomingData(int i) {
bool res = true;
/* Handle data send from client */
int* connData = (int*) events[i].data.ptr;
if ((events[i].events & EPOLLHUP) || (events[i].events & EPOLLERR)) {
/* Error occured */
printf("Epoll error occurred\n");
close(*connData);
free(connData);
} else if (EPOLLIN == events[i].events) {
/* Delete the read event */
res = modifyEpoll(epollfd, EPOLL_CTL_DEL, *connData, 0, 0);
if (false == res) {
goto Exit;
}
/* Handle write in a new thread */
//TODO: integrate threadpool
pthread_t thrd;
if (0 != pthread_create(&thrd, NULL, threadMethod, connData)) {
res = false;
}
pthread_join(thrd, NULL);
}
Exit: return res;
}
sendfile ():
void* threadMethod(void* connFd) {
int* connData = (int*) connFd;
int fd = *connData;
/* Transfer using sendfile */
struct stat stat_buf;
off_t offset = 0;
fstat(fd, &stat_buf);
int res = sendfile(file, fd, &offset, 10);
printf("res = %d\n", res);
printf("errno = %d\n", errno);
…
Return NULL;
}
sendfile()
возвращает -1 и значение errno равно 29.