Как отфильтровать события epoll?

Допустим, я слушаю через несколько сетевых портов:
80 с ПТС
81-250 с UDP

Это требует нескольких различных способов обработки входных данных.
— Новый сокет на порту 80 (добавить новый дескриптор файла в список epoll)
— Чтение из клиентского сокета на порту 80
— Читать с любого из 170 портов UDP

Это довольно разные дескрипторы, хотя я бы хотел использовать epoll, чтобы реагировать только на те, которые обновляются.
Есть ли способ отфильтровать события epoll, чтобы каждое событие получало необходимый дескриптор, не просматривая все файловые дескрипторы?

Заранее спасибо,
Sinned

Пример кода:

int epfd = epoll_create( 10 );

int tcpFd = createTCPSocket( 80 );
registerListenEvent( epfd, tcpFd );

int udpFds[ 170 ];
for ( int i = 0; i < 170; i++ ) {
udpSockets[ i ] = createUdpSocket( 81 + i );
registerUdpPacketEvent( epfd, udpFds[ i ] );
}

int tcpClientFds[ 256 ];
int tcpClientId = 0;

struct epoll_event events[ 64 ];

while ( 1 ) {
int nfds = epoll_wait( epfd, events, 64, -1 );
for ( int i = 0; i < nfds; i++ ) {
struct epoll_event event = events[ i ];
int fd = event.data.fd;

// This kind of filtering can take quite a while
if ( fd == tcpFd ) {
int acceptedFd = accept( tcpFd );
registerTcpClientEvent( epfd, acceptedFd );
tcpClientFds[ tcpClientId++ ] = acceptedFd;
} else {
for ( int i = 0; i < 170; i++ )
if ( udpFds[ i ] == fd ) {
handleUdpMessage( fd );
return;
}
for ( int i = 0; i < tcpClientId; i++ ) {
if ( tcpClientFds[ i ] == fd ) {
handleTcpMessage( fd );
return;
}
}
}
}
}

Вы можете вообразить, что прохождение 170 — 426 циклов для каждого события может быть довольно дорогостоящим.
Я надеялся, что это событие можно будет определить без этого.
Это возможно?

1

Решение

epoll() говорит вам точный файловый дескриптор (ы), который вызвал событие (я). Вам не нужно охотиться за ними. Читать документацию для примера. epoll_wait() дает вам массив epoll_event структуры, по одному на каждый удовлетворенный файловый дескриптор. epoll_event структура имеет fd член. Вы бы зарегистрировали свои индивидуальные розетки для EPOLLIN события, а затем каждый раз epoll_wait() отчеты о выполненных событиях, вы будете читать только из сообщенных сокетов по мере необходимости.

1

Другие решения

Как упомянуто «remy», создайте свою собственную структуру для сокета и добавьте ее в событие. Когда событие сработало, сначала обратитесь к вашей структуре и начните обработку.

    struct epoll_event event = {0, {NULL, 0, 0, 0}};
int s = 0;

event.data.fd = tp->task_socket;
event.data->ptr = tp;
event.events = EPOLLOUT;

assert(efd);

s = epoll_ctl (efd, EPOLL_CTL_DEL, tp->task_socket, &event);

часть обработки:

дело EPOLLOUT:
tp = (задача *) ev-> data-> ptr;

Этот тп должен рассказать все о ваших сокетах и ​​функции обработки ..

0

По вопросам рекламы [email protected]