UNIX: разработка сетевых приложений
Шрифт:
Сервер, показанный в листинге 1.5, называется последовательным сервером( iterative server), поскольку он обслуживает клиентов последовательно, по одному клиенту за один раз. Существует несколько технологий написания параллельного сервера( concurrent server), который обслуживает множество клиентов одновременно. Самой простой технологией является вызов функции Unix
Запуская такой сервер из командной строки, мы обычно рассчитываем, что он будет работать достаточно долго, поскольку часто серверы работают, пока работает система. Поэтому мы должны модифицировать код сервера таким образом, чтобы он корректно работал как демон( daemon) Unix, то есть процесс, функционирующий в фоновом режиме без подключения к терминалу. Это решение подробно описано в разделе 13.4.
1.6.
Технологии сетевого программирования иллюстрируются в этой книге на двух основных примерах:
клиент-сервер времени и даты (описание которого мы начали в листингах 1.1, 1.2 и 1.5), и
эхо-клиент-сервер (который появится в главе 5).
Чтобы обеспечить удобный поиск различных тем, которых мы касаемся в этой книге, мы объединили разработанные нами программы и сопроводили их номерами листингов, в которых приведен исходный код. В табл. 1.1 перечислены версии клиента времени и даты (две из них мы уже видели). В табл. 1.2 перечисляются версии сервера времени и даты. В табл. 1.3 представлены версии эхо-клиента, а в табл. 1.4 — версии эхо-сервера.
Таблица 1.1. Различные версии клиента времени и даты
Листинг | Описание |
---|---|
1.1 | TCP/Ipv4, зависимый от протокола |
1.2 | TCP/Ipv6, зависимый от протокола |
11.2 | TCP/Ipv4, зависимый от протокола, вызывает функции gethostbyname и getservbyname |
11.5 | TCP, независимый от протокола, вызывает функции getaddrinfo и tcp_connect |
11.10 | UDP, независимый от протокола, вызывает функции getaddrinfo и udp_connect |
16.7 | TCP, использует неблокирующую функцию connect |
31.2 | TCP/IPv4, зависимый от протокола |
Д.1 | TCP, зависимый от протокола, генерирует SIGPIPE |
Д.2 | TCP, зависимый от протокола, печатает размер буфера сокета и MSS |
Д.5 | TCP, зависимый от протокола, допускает использование имени узла (функция gethostbyname) или IP-адреса |
Д.6 | TCP, независимый от протокола, допускает использование имени узла (функция gethostbyname). |
Таблица 1.2. Различные версии сервера времени и даты, рассматриваемые в данной книге
Листинг | Описание |
---|---|
1.5 | TCP/IPv4, зависимый от протокола |
11.7 | TCP, независимый от протокола, вызывает getaddrinfo и tcp_listen |
11.8 | TCP, независимый от протокола, вызывает getaddrinfo и tcp_listen |
11.13 | UDP, независимый от протокола, вызывает getaddrinfo и udp_server |
13.2 | TCP, независимый от протокола, выполняется как автономный демон |
13.4 | TCP, независимый от протокола, порожденный демоном inetd |
Таблица 1.3. Различные версии эхо-клиента, рассматриваемые в данной книге
Листинг | Описание |
---|---|
5.3 | TCP/IPv4, зависимый от протокола |
6.1 | TCP, использует функцию select |
6.2 | TCP, использует функцию select и работает в пакетном режиме |
8.3 | UDP/IPv4, зависимый от протокола |
8.5 | UDP, проверяет адрес сервера |
8.7 | UDP, вызывает функцию connect для получения асинхронных ошибок |
14.2 | UDP, тайм-аут при чтении ответа сервера с использованием сигнала SIGALRM |
14.4 | UDP, тайм-аут при чтении ответа сервера с использованием функции select |
14.5 | UDP, тайм-аут при чтении ответа сервера с использованием опции сокета SO_RCVTIMEO |
14.7 | TCP, использует интерфейс /dev/poll |
14.8 | TCP, использует интерфейс kqueue |
15.4 | Поток домена Unix, зависит от протокола |
15.6 | Дейтаграмма домена Unix, зависит от протокола |
16.1 | TCP, использует неблокируемый ввод-вывод |
16.6 | TCP, использует два процесса (функцию fork) |
16.14 | TCP, устанавливает соединение, затем посылает пакет RST |
20.1 | UDP, широковещательный, ситуация гонок |
20.2 | UDP, широковещательный, ситуация гонок |
20.3 | UDP, широковещательный, для устранения ситуации гонок используется функция pselect |
20.5 | UDP, широковещательный, для устранения ситуации гонок используются функции sigsetjmp и siglongmp |
20.6 | UDP, широковещательный, для устранения ситуации гонок в обработчике сигнала используется IPC |
22.4 | UDP, увеличение надежности протокола за счет применения повторной передачи, тайм-аутов и порядковых номеров |
26.1 | TCP, использование двух потоков |
27.4 | TCP/IPv4, задание маршрута от отправителя |
27.5 | UDP/IPv6, задание маршрута от отправителя |
Таблица 1.4. Различные версии эхо-сервера, рассматриваемые в данной книге
Листинг | Описание |
---|---|
5.1 | TCP/IPv4, зависимый от протокола |
5.9 | TCP/IPv4, зависимый от протокола, корректно обрабатывает завершение всех дочерних процессов |
6.3 | TCP/IPv4, зависимый от протокола, использует функцию select, один процесс обрабатывает всех клиентов |
6.5 | TCP/IPv4, зависимый от протокола, использует функцию poll, один процесс обрабатывает всех клиентов |
8.1 | UDP/IPv4, зависимый от протокола |
8.14 | TCP и UDP/IPv4, зависимый от протокола, использует функцию select |
14.6 | TCP, использует стандартный ввод-вывод |
15.3 | Доменный сокет Unix, зависимый от протокола |
15.5 | Дейтаграмма домена Unix, зависит от протокола |
15.13 | Доменный сокет Unix, с передачей данных, идентифицирующих клиента |
22.3 | UDP, печатает полученный IP-адрес назначения и имя полученного интерфейса, обрезает дейтаграммы |
22.13 | UDP, связывает все адреса интерфейсов |
25.2 | UDP, использование модели ввода-вывода, управляемого сигналом |
26.2 | TCP, один поток на каждого клиента |
26.3 | TCP, один поток на каждого клиента, машинонезависимая (переносимая) передача аргумента |
27.4 | TCP/IPv4, печатает полученный маршрут от отправителя |
27.6 | UDP/IPv4, печатает полученный маршрут от отправителя и обращает его |
28.21 | UDP, использует функцию icmpd для получения асинхронных ошибок |
Д.9 | UDP, связывает все адреса интерфейсов |
1.7. Модель OSI
Распространенным способом описания уровней сети является предложенная Международной организацией по стандартизации (International Standards Organization, ISO) модель взаимодействия открытых систем( open systems interconnection, OSI). Эта семиуровневая модель показана на рис. 1.5, где она сравнивается со стеком протоколов Интернета.
Рис. 1.5. Уровни модели OSI и набор протоколов Интернета
Мы считаем, что два нижних уровня модели OSI соответствуют драйверу устройства и сетевому оборудованию, которые имеются в системе. Обычно нам не приходится беспокоиться об этих уровнях, за исключением того, что мы должны знать некоторые свойства канального уровня — например, что MTU (максимальная единица передачи) Ethernet, которая описывается в разделе 2.11, имеет размер 1500 байт.
Сетевой уровень управляется протоколами IPv4 и IPv6, оба они описываются в приложении А. Из протоколов транспортного уровня мы можем выбирать TCP, UDP и SCRIPT, они описываются в главе 2. На рис. 1.5 изображен разрыв между TCP и UDP; это означает, что приложение может обойти транспортный уровень и использовать IPv4 или IPv6 непосредственно. В таких случаях речь идет о символьных сокетах( raw socket), которые будут описаны в главе 28.
Три верхних уровня модели OSI соответствуют уровню приложений. Приложением может быть веб-клиент (браузер), клиент Telnet, веб-сервер, сервер FTP или любое другое используемое нами приложение. В случае протоколов Интернета три верхние уровня модели OSI разделяются очень редко.
Описанный в этой книге API сокетов является интерфейсом между верхними тремя уровнями («приложением») и транспортным уровнем. Это один из важнейших вопросов книги: как создавать приложения, используя сокеты TCP и UDP. Мы уже упоминали о символьных сокетах, и в главе 29 мы увидим, что можем даже полностью обойти уровень IP, чтобы читать и записывать свои собственные кадры канального уровня.
Почему сокеты предоставляют интерфейс между верхними тремя уровнями модели OSI и транспортным уровнем? Для подобной организации модели OSI имеются две причины, которые мы отобразили на правой стороне рис. 1.5. Прежде всего, три верхних уровня отвечают за все детали, имеющие отношение к приложению (например, FTP, Telnet, HTTP), но знают мало об особенностях взаимодействия по сети. Четыре же нижних уровня знают мало о приложении, но отвечают за все, что связано с коммуникацией: отправку данных, ожидание подтверждения, упорядочивание данных, приходящих не в должном порядке, расчет и проверку контрольных сумм и т.д. Второй же причиной является то, что верхние три уровня часто формируют так называемый пользовательский процесс( user process), в то время как четыре нижних уровня обычно поставляются как часть ядра операционной системы. Unix, как и многие современные операционные системы, обеспечивает разделение пользовательского процесса и ядра. Следовательно, интерфейс между уровнями 4 и 5 является естественным местом для создания API.