Вход/Регистрация
UNIX: разработка сетевых приложений
вернуться

Стивенс Уильям Ричард

Шрифт:

48 error != 0) {

49 err_ret("nonblocking connect failed

50 for %s", file[i].f_name);

51 }

52 /* соединение установлено */

53 printf("connection established for %s\n", file[i].f_name);

54 FD_CLR(fd, &wset); /* отключаем запись в этот сокет */

55 write_get_cmd(&file[i]); /* передаем команду GET */

56 } else if (flags & F_READING && FD_ISSET(fd, &rs)) {

57 if ((n = Read(fd, buf, sizeof(buf))) == 0) {

58 printf("end-of-file on %s\n", file[i].f_name);

59 Close(fd);

60 file[i].f_flags = F_DONE; /* сбрасывает флаг F_READING */

61 FD_CLR(fd, &rset);

62 nconn--;

63 nlefttoread--;

64 } else {

65 printf("read %d bytes from %s\n", n, file[i].f_name);

66 }

67 }

68 }

69 }

70 exit(0);

71 }

Обработка всех готовых дескрипторов

39-55
Теперь мы анализируем каждый элемент массива структур
file
, чтобы определить, какие дескрипторы нужно обрабатывать. Если установлен флаг
F_CONNECTING
и дескриптор включен либо в наборе чтения, либо в наборе записи, неблокируемая функция
connect
завершается. Как мы говорили при описании листинга 16.7, мы вызываем функцию
getsockopt
, чтобы получить ожидающую обработки ошибку для сокета. Если значение ошибки равно нулю, соединение успешно завершилось. В этом случае мы выключаем дескриптор в наборе флагов записи и вызываем функцию
write_get_cmd
для отправки запроса HTTP серверу.

Проверка, есть ли у дескриптора данные

56-67
Если установлен флаг
F_READING
и дескриптор готов для чтения, мы вызываем функцию
read
. Если соединение было закрыто другим концом, мы закрываем сокет, устанавливаем флаг
F_DONE
, выключаем дескриптор в наборе чтения и уменьшаем число активных соединений и общее число соединений, требующих обработки.

Есть два способа оптимизации, которые мы не используем в этом примере (чтобы не усложнять его еще больше). Во-первых, мы можем завершить цикл for в листинге 16.13, когда мы обработали число дескрипторов, которые, по сообщению функции

select
, были готовы. Во-вторых, мы могли, где это возможно, уменьшить значение
maxfd
, чтобы функция
select
не проверяла биты дескрипторов, которые уже сброшены. Поскольку число дескрипторов, используемых в этом коде, в любой момент времени, вероятно, меньше 10, а не порядка тысяч, вряд ли какая-либо из этих оптимизаций стоит дополнительных усложнений.

Эффективность одновременных соединений

Каков выигрыш в эффективности при установлении множества одновременных соединений? В табл. 16.1 показано время, необходимое для выполнения определенной задачи, которая состоит в том, чтобы получить от веб-сервера домашнюю страницу и девять картинок. Время обращения RTT для данного соединения с сервером равно приблизительно 150 мс. Размер домашней страницы — 4017 байт, а средний размер девяти файлов с изображениями составил 1621 байт. Размер сегмента TCP равен 512 байт. Для сравнения мы также представляем в этой таблице значения для многопоточной версии данной программы, которую мы создаем в разделе 26.9.

Таблица 16.1. Время выполнения задания для разного количества одновременных соединений в разных версиях программы

Количество одновременных соединений Затраченное время (в секундах), отсутствие блокирования Затраченное время (в секундах), использование потоков
1 6,0 6,3
2 4,1 4,2
3 3,0 3,1
4 2,8 3,0
5 2,5 2,7
6 2,4 2,5
7 2,3 2,3
8 2,2 2,3
9 2,0 2,3
ПРИМЕЧАНИЕ

Мы показали пример использования одновременных соединений, поскольку он служит хорошей иллюстрацией применения неблокируемого ввода-вывода, а также потому, что в данном случае эффективность применения одновременных соединений может быть измерена. Это свойство также используется в популярном приложении — веб-браузере Netscape. В этой технологии могут появиться некоторые «подводные камни», если сеть перегружена. В главе 21 [111] подробно описываются алгоритмы TCP, называемые алгоритмами медленного старта (slow start) и предотвращения перегрузки сети (congestion avoidance). Когда от клиента к серверу устанавливается множество соединений, то взаимодействие между соединениями на уровне TCP отсутствует. То есть если на одном из соединений происходит потеря пакета, другие соединения с тем же сервером не получают соответствующего уведомления, и вполне возможно, что другие соединения вскоре также столкнутся с потерей пакетов, пока не замедлятся. По этим дополнительным соединениям будет продолжаться отправка слишком большого количества пакетов в уже перегруженную сеть. Эта технология также увеличивает нагрузку на сервер.

  • Читать дальше
  • 1
  • ...
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: