Выбор метода опроса зависит от ОС.На linux используйте epoll, желательно с триггером.На FreeBSD используйте kqueue.В Windows используйте, например, WSAEventSelect и WSAWaitForMultipleEvents.
Ваш основной цикл должен быть просто:
for (;;) {
epoll(); // blocking poll until an event happens, optionally with a timeout
// iterate signaled sockets and process data
// Other tasks
}
Независимо от того, хотите ли вы реализовать это в каждом потоке в пуле потоков, или только один раз вОсновной поток, зависит от остальной части вашего приложения.Ключ должен позволить функции опроса подождать, таким образом вы не будете использовать чрезмерную загрузку ЦП.
Вы можете использовать неблокирующие сокеты или ioctl(FIONREAD...
, чтобы проверить, сколько данных читается на каждомразъем.
Мой предпочтительный дизайн ООП для обработки сокетов состоит в том, чтобы сделать сокет полностью не осведомленным о обработчике сокетов.Опросник сокетов, скрывающий фактическую функцию, используемую для опроса, будет принимать сокеты и события, которые он должен отслеживать, опрашивать, например, в функции tick()
, а затем сообщать каждому сокету или внешний класс прослушивания, чтоесть что-то, что можно сделать с сокетом.Что-то вроде:
class SocketPoller {
public:
void registerSocket(Socket * s, int EventMask);
void unregisterSocket(Socket * s);
virtual void tick() = 0;
}
class SocketPollerEPoll : public SocketPoller {
public:
void tick() {
epoll(...);
// for each socket with events:
TheSocket->notifyReadable();
}
};
class SocketPollerSelect : public SocketPoller {
public:
void tick() {
select(...);
// for each socket with events:
TheSocket->notifyReadable();
}
};