Уильям Стивенс - UNIX: разработка сетевых приложений

Тут можно читать онлайн Уильям Стивенс - UNIX: разработка сетевых приложений - бесплатно ознакомительный отрывок. Жанр: comp-osnet, издательство Питер, год 2007. Здесь Вы можете читать ознакомительный отрывок из книги онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    UNIX: разработка сетевых приложений
  • Автор:
  • Жанр:
  • Издательство:
    Питер
  • Год:
    2007
  • Город:
    Санкт-Петербург
  • ISBN:
    5-94723-991-4
  • Рейтинг:
    4.33/5. Голосов: 91
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание

UNIX: разработка сетевых приложений - описание и краткое содержание, автор Уильям Стивенс, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.

UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок

UNIX: разработка сетевых приложений - читать книгу онлайн бесплатно (ознакомительный отрывок), автор Уильям Стивенс
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать
Рис 617 Структуры данных после того как первый клиент разрывает соединение - фото 61

Рис. 6.17. Структуры данных после того как первый клиент разрывает соединение

Итак, по мере того как приходят клиенты, мы записываем дескриптор их присоединенного сокета в первый свободный элемент массива client(то есть в первый элемент со значением -1). Следует также добавить присоединенный сокет в набор дескрипторов для чтения. Переменная maxi— это наибольший используемый в данный момент индекс в массиве client, а переменная maxfd(плюс один) — это текущее значение первого аргумента функции select. Единственным ограничением на количество обслуживаемых сервером клиентов является минимальное из двух значений: FD_SETSIZEи максимального числа дескрипторов, которое допускается для данного процесса ядром (о чем мы говорили в конце раздела 6.3).

В листинге 6.3 показана первая половина этой версии сервера.

Листинг 6.3. Сервер TCP, использующий одиночный процесс и функцию select: инициализация

//tcpcliserv/tcpservselect01.c

1 #include "unp.h"

2 int

3 main(int argc, char **argv)

4 {

5 int i, maxi, maxfd, listenfd, connfd, sockfd;

6 int nready, client[FD_SETSIZE],

7 ssize_t n;

8 fd_set rset, allset;

9 char buf[MAXLINE];

10 socklen_t clilen;

11 struct sockaddr_in cliaddr, servaddr;

12 listenfd = Socket(AF_INET, SOCK_STREAM, 0);

13 bzero(&servaddr, sizeof(servaddr));

14 servaddr.sin_family = AF_INET;

15 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

16 servaddr.sin_port = htons(SERV_PORT);

17 Bind(listenfd, (SA*)&servaddr, sizeof(servaddr));

18 Listen(listenfd, LISTENQ);

19 maxfd = listenfd; /* инициализация */

20 maxi = -1; /* индекс в массиве client[] */

21 for (i = 0; i < FD_SETSIZE; i++)

22 client[i] = -1; /* -1 означает свободный элемент */

23 FD_ZERO(&allset);

24 FD_SET(listenfd, &allset);

Создание прослушиваемого сокета и инициализация функции select

12-24 Этапы создания прослушиваемого сокета те же, что и раньше: вызов функций socket, bindи listen. Мы инициализируем структуры данных при том условии, что единственный дескриптор, который мы с помощью функции selectвыберем, изначально является прослушиваемым сокетом.

Вторая половина функции mainпоказана в листинге 6.4.

Листинг 6.4. Сервер TCP, использующей одиночный процесс и функцию select: цикл

//tcpcliserv/tcpservselect01.c

25 for (;;) {

26 rset = allset; /* присваивание значения структуре */

27 nready = Select(maxfd + 1, &rset, NULL, NULL, NULL);

28 if (FD_ISSET(listenfd, &rset)) { /* соединение с новым клиентом */

29 clilen = sizeof(cliaddr);

30 connfd = Accept(listenfd, (SA*)&cliaddr, &clilen);

31 for (i = 0; i < FD_SETSIZE; i++)

32 if (client[i] < 0) {

33 client[i] = connfd; /* сохраняем дескриптор */

34 break;

35 }

36 if (i == FD_SETSIZE)

37 err_quit("too many clients");

38 FD_SET(connfd, &allset); /* добавление нового дескриптора */

39 if (connfd > maxfd)

40 maxfd = connfd; /* для функции select */

41 if (i > maxi)

42 maxi = i; /* максимальный индекс в массиве clientf[] */

43 if (--nready <= 0)

44 continue; /* больше нет дескрипторов, готовых для чтения */

45 }

46 for (i = 0; i <= maxi; i++) { /* проверяем все клиенты на наличие

данных */

47 if ((sockfd - client[i]) < 0)

48 continue;

49 if (FD_ISSET(sockfd, &rset)) {

50 if ((n = Read(sockfd, buf, MAXLINE)) == 0) {

51 /* соединение закрыто клиентом */

52 Close(sockfd);

53 FD_CLR(sockfd, &allset);

54 client[i] = -1;

55 } else

56 Writen(sockfd, line, n);

57 if (--nready <= 0)

58 break; /* больше нет дескрипторов, готовых для чтения */

59 }

60 }

61 }

62 }

Блокирование в функции select

26-27 Функция selectждет, пока не будет установлено новое клиентское соединение или на существующем соединении не прибудут данные, сегмент FIN или сегмент RST.

Принятие новых соединений с помощью функции accept

28-45 Если прослушиваемый сокет готов для чтения, новое соединение установлено. Мы вызываем функцию acceptи соответствующим образом обновляем наши структуры данных. Для записи присоединенного сокета мы используем первый незадействованный элемент массива client. Число готовых дескрипторов уменьшается, и если оно равно нулю, мы можем не выполнять следующий цикл for. Это позволяет нам использовать значение, возвращаемое функцией select, чтобы избежать проверки не готовых дескрипторов.

Проверка существующих соединений

46-60 Каждое существующее клиентское соединение проверяется на предмет того, содержится ли его дескриптор в наборе дескрипторов, возвращаемом функцией select. Если да, то из этого дескриптора считывается строка, присланная клиентом, и отражается обратно клиенту. Если клиент закрывает соединение, функция read возвращает нуль и мы обновляем структуры соответствующим образом.

Мы не уменьшаем значение переменной maxi, но могли бы проверять возможность сделать это каждый раз, когда клиент закрывает свое соединение.

Этот сервер сложнее, чем сервер, показанный в листингах 5.1 и 5.2, но он позволяет избежать затрат на создание нового процесса для каждого клиента, что является хорошим примером использования функции select. Тем не менее в разделе 15.6 мы опишем проблему, связанную с этим сервером, которая, однако, легко устраняется, если сделать прослушиваемый сокет неблокируемым, а затем проверить и проигнорировать несколько ошибок из функции accept.

Атака типа «отказ в обслуживании»

К сожалению, функционирование только что описанного сервера вызывает проблемы. Посмотрим, что произойдет, если некий клиент-злоумышленник соединится с сервером, отправит 1 байт данных (отличный от разделителя строк) и войдет в состояние ожидания. Сервер вызовет функцию readline, которая прочитает одиночный байт данных от клиента и заблокируется в следующем вызове функции read, ожидая следующих данных от клиента. Сервер блокируется (вернее, «подвешивается») этим клиентом и не может предоставить обслуживание никаким другим клиентам (ни новым клиентским соединениям, ни данным существующих клиентов), пока упомянутый клиент-злоумышленник не отправит символ перевода строки или не завершит свой процесс.

Дело в том, что обрабатывая множество клиентов, сервер никогда не должен блокироваться в вызове функции, относящейся к одному клиенту. В противном можно «подвесить» сервер, что приведет к отказу в обслуживании для всех остальных клиентов. Это называется атакой типа «отказ в обслуживании» (DoS attack — Denial of Service). Такая атака воздействует на сервер, делая невозможным обслуживание нормальных клиентов. Обезопасить себя от подобных атак позволяют следующие решения: использовать неблокируемый ввод-вывод (см. главу 16), предоставлять каждому клиенту обслуживание отдельным потоком (например, для каждого клиента порождать процесс или поток) или установить тайм-аут для ввода-вывода (см. раздел 14.2).

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Уильям Стивенс читать все книги автора по порядку

Уильям Стивенс - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




UNIX: разработка сетевых приложений отзывы


Отзывы читателей о книге UNIX: разработка сетевых приложений, автор: Уильям Стивенс. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x