Вопросы об асинхронных сокетах

Хорошо, я узнал в этом вопросе, что опрос сокетов не масштабируется, поэтому я решил изучить асинхронный сокеты, и у меня есть несколько вопросов.

  1. Если у меня есть несколько сотен клиентов, пытающихся отправить данные своему партнеру, какой асинхронный метод лучше всего использовать? select() poll() или я могу просто вызвать recv() для неблокирующего сокета?
  2. Когда я опрашиваю и обнаруживаю, что есть данные для чтения, должен ли я создать поток, чтобы позаботиться об этом?
  3. Должен ли я беспокоиться о какой-либо функции сна, или я должен просто позволить программе использовать 100% ЦП?
  4. Будет ли вообще эффективно помещать всю эту функциональность в класс? Я бы очень хотел сделать что-то вроде этого:

//thread 1:  
while(!quit){  
   manager.check_clients();  
   manager.handle_clients();  
   manager.display_clients();  
 }
//thread 2:
while(!quit)
  manager.manage_admin_input();

person ultifinitus    schedule 07.03.2011    source источник
comment
Спасибо, Джон, по какой-то причине я удалил свое двоеточие.   -  person ultifinitus    schedule 08.03.2011


Ответы (3)


Выбор метода опроса зависит от ОС. В 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();
  }
};
person Erik    schedule 07.03.2011
comment
Итак, когда я опрашиваю сокеты, могу ли я опрашивать большую группу на основе моего порта подключения, или мне нужно опрашивать каждое отдельное соединение на основе конкретного порта для каждого? (Извините, я никогда раньше не занимался программированием асинхронных сокетов, я, вероятно, просто окунусь в него, как только получу общую идею) - person ultifinitus; 08.03.2011
comment
Сначала реализуйте что-нибудь на основе select() — с этого легко начать. Идея состоит в том, чтобы передать набор сокетов функции опроса. Затем функция опроса сообщит вам о подмножестве сокетов, в которых произошло событие. Вы можете настроить 50 сокетов и выбрать их удобочитаемость, и выбор может вернуться, сообщив вам, что эти 6 удобочитаемы. - person Erik; 08.03.2011
comment
Ой! В этом есть смысл! Спасибо! Я начну с select() сейчас, я дам вам знать, как это происходит. - person ultifinitus; 08.03.2011

Несмотря на то, что на этот вопрос уже был дан ответ, вы можете рассмотреть возможность использования Boost.Asio для вашей системы коммуникации. Он красиво упаковывает различные методы опроса на различных платформах в чистую, согласованную и типобезопасную библиотеку только заголовков. Он разработан, хорошо поддерживается и часто обсуждается на SO.

person Sam Miller    schedule 08.03.2011
comment
Я видел, как это обсуждалось в разных местах. Знаете ли вы, каковы сравнения скорости (между низкоуровневыми сокетами и библиотекой повышения)? - person ultifinitus; 08.03.2011

Вы можете использовать платформу Push, http://www.pushframework.com. Она эффективно использует асинхронные операции ввода-вывода. Также будет абстрагироваться от низкоуровневых деталей, чтобы вы могли сосредоточиться на бизнес-логике вашего приложения.

person charfeddine.ahmed    schedule 30.05.2011