Настройка сетевого сокета может оказаться довольно сложной, так как вам необходимо учесть тип сокета, IP-адреса, порты и в некоторых случаях транспортный протокол. Однако, когда все начальные подробности приведены в порядок, серверы используют стандартные методы для работы с входящим сетевым трафиком.
Схема на рис. 10.1 показывает, сколько серверов обслуживают соединения от входящих сокетов потоков. Обратите внимание на то, что этот тип серверов затрагивает два типа сокетов: сокет прослушивания и сокет для чтения и записи. Основной процесс использует сокет прослушивания для поиска подключений от сети. Когда возникает новое подключение, основной процесс применяет системный вызов accept(), чтобы принять подключение, создав при этом сокет чтения/записи, предназначенный для этого соединения. После этого основной процесс использует команду fork(), чтобы создать новый дочерний процесс для работы с новым соединением. Наконец, исходный сокет остается в роли прослушивателя и продолжает поиск новых подключений от имени основного процесса.
Когда процесс настроит сокет определенного типа, он может взаимодействовать с ним подходящим для этого сокета способом. Именно это делает сокеты гибкими: если вам необходимо изменить лежащий в основе транспортный уровень, вам не потребуется переписывать все части кода, которые отвечают за отправку и получение данных; вам понадобится лишь изменить код инициализации.
Если вы программист и хотели бы изучить, как использовать интерфейс сокетов, то классическим руководством является 3-е издание книги У. Ричарда Стефенса (W. Richard Stephens), Билла Феннера (Bill Fenner) и Эндрю М. Рудоффа (Andrew M. Rudoff) Unix Network Programming, Volume 1 («Программирование для сетей Unix. Том 1», Addison-Wesley Professional, 2003). Во втором томе рассмотрено также межпроцессное взаимодействие.
Рис. 10.1. Один из методов принятия и обработки входящих соединений
10.10. Сокеты домена Unix
Приложения, которые используют сетевые средства, не обязаны задействовать два отдельных хоста. Многие приложения разработаны как механизмы «клиент — сервер» или «узел — узел», в которых процессы, запущенные на одном и том же компьютере, используют межпроцессное взаимодействие (IPC), чтобы выяснить, какую работу необходимо выполнить и кто этим займется. Вспомните, например, о том, что демоны вроде systemd и NetworkManager используют шину D-Bus для отслеживания системных событий и реагирования на них.
Процессы могут использовать для взаимодействия обычную IP-связь через локальный хост сети (127.0.0.1), но вместо этого, как правило, применяется специальный тип сокета, о котором мы вкратце упомянули в главе 3, — сокет домена Unix. Когда процесс подключается к сокету домена Unix, он ведет себя почти так же, как и сетевой сокет: может прослушивать и принимать подключения к сокету, и вы можете даже выбирать между различными типами сокетов, чтобы он работал как сокет TCP или UDP.
примечание
Важно помнить о том, что сокет домена Unix не является сетевым сокетом и за ним не расположено никакой сети. Для его использования даже нет необходимости настраивать сеть. К тому же сокеты домена Unix не должны быть привязаны к файлам сокетов. Процесс может создать безымянный сокет домена Unix и сообщить его адрес другому процессу.
10.10.1. Преимущества для разработчиков
Разработчикам нравятся сокеты домена Unix для межпроцессного взаимодействия. На это есть две причины. Во-первых, эти сокеты дают возможность использовать специальные файлы сокетов в файловой системе для контроля доступа, чтобы любой процесс, у которого нет доступа к файлу сокета, не смог применить сокет. Поскольку здесь отсутствует взаимодействие с сетью, такой вариант проще и дает меньше поводов для стандартных вторжений в сеть. Например, в каталоге /var/run/dbus обычно можно обнаружить такой файл сокета для шины D-Bus:
$ ls -l /var/run/dbus/system_bus_socket
srwxrwxrwx 1 root root 0 Nov 9 08:52 /var/run/dbus/system_bus_socket
Во-вторых, поскольку ядру Linux при работе с сокетами домена Unix не приходится проходить через множество уровней сетевой подсистемы, производительность при этом улучшается.
Написание программного кода для сокетов домена Unix не сильно отличается от поддержки обычных сетевых сокетов. Поскольку преимущества от этого могут быть существенными, некоторые сетевые серверы осуществляют взаимодействие как по сети, так и через сокеты домена Unix. Например, сервер mysqld базы данных MySQL способен принимать клиентские соединения от удаленных хостов, и он же обычно предлагает сокет домена Unix в файле /var/run/mysqld/mysqld.sock.
10.10.2. Просмотр списка сокетов домена Unix
Можно просмотреть список сокетов домена Unix, которые в данный момент использованы в системе, с помощью команды lsof -U:
# lsof -U
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 19701 mysql 12u unix 0xe4defcc0 0t0 35201227 /var/run/mysqld/
mysqld.sock
chromium- 26534 juser 5u unix 0xeeac9b00 0t0 42445141 socket
tlsmgr 30480 postfix 5u unix 0xc3384240 0t0 17009106 socket
tlsmgr 30480 postfix 6u unix 0xe20161c0 0t0 10965 private/tlsmgr
—snip—
Этот перечень будет довольно длинным, так как многие современные приложения широко используют безымянные сокеты. Их можно узнать по идентификатору socket в столбце NAME такого отчета.
11. Введение в сценарии оболочки
Если вы можете вводить команды в оболочке, то это означает, что вы можете создавать сценарии оболочки (известные также как сценарии оболочки Bourne shell). Сценарий оболочки — это набор команд, записанных в файл. Оболочка считывает эти команды из файла так, словно вы вводите их в терминале.
11.1. Основы сценариев оболочки
Сценарии оболочки Bourne shell обычно начинаются с приведенной ниже строки, которая указывает на то, что инструкции в файле сценария должна выполнять команда /bin/sh. Убедитесь в том, что в начале файла сценария нет пробелов.
#!/bin/sh
Фрагмент #! (в англоязычных источниках он называется shebang) будет часто встречаться в других сценариях этой книги. Можно перечислить любые команды, исполнение которых вы желаете поручить оболочке, указав их после строки #!/bin/sh. Например, так:
#!/bin/sh
#
# Print something, then run ls
echo About to run the ls command.
ls
примечание
Символ # в начале строки указывает на то, что данная строка является комментарием, то есть оболочка проигнорирует все, что расположено в строке после этого символа. Используйте комментарии, чтобы объяснить трудные для понимания части ваших сценариев.
После создания сценария оболочки и настройки прав доступа можно запустить его, поместив файл сценария в один из каталогов вашего командного пути, а затем набрав имя сценария в командной строке. Можно также запустить команду ./script, если этот сценарий расположен в вашем текущем рабочем каталоге, или же использовать полный путь.
Как и для других команд Unix, необходимо установить исполняемый бит для файла сценария оболочки, но при этом следует также установить бит чтения, чтобы оболочка могла читать этот файл. Проще всего это выполнить следующим образом:
$ chmod +rx script
Команда chmod позволяет другим пользователям читать и исполнять сценарий. Если вы желаете запретить это, используйте абсолютный режим файла 700 (и обратитесь заодно к разделу 2.17, чтобы освежить свои знания о правах доступа).