Допустим, я слушаю через несколько сетевых портов:
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 циклов для каждого события может быть довольно дорогостоящим.
Я надеялся, что это событие можно будет определить без этого.
Это возможно?
epoll()
говорит вам точный файловый дескриптор (ы), который вызвал событие (я). Вам не нужно охотиться за ними. Читать документацию для примера. epoll_wait()
дает вам массив epoll_event
структуры, по одному на каждый удовлетворенный файловый дескриптор. epoll_event
структура имеет fd
член. Вы бы зарегистрировали свои индивидуальные розетки для EPOLLIN
события, а затем каждый раз epoll_wait()
отчеты о выполненных событиях, вы будете читать только из сообщенных сокетов по мере необходимости.
Как упомянуто «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;
Этот тп должен рассказать все о ваших сокетах и функции обработки ..