Вызов функций bind и getsockname

12-18 Мы копируем аргумент командной строки, используя функцию strncpy, чтобы избежать переполнения структуры, если полное имя слишком длинное. Поскольку мы инициализируем структуру нулем и затем вычитаем единицу из размера массива sun_path, мы знаем, что полное имя оканчивается нулем. Далее вызывается функция bind и мы используем макрос SUN_LEN для вычисления длины аргумента функции. Затем мы вызываем функцию getsockname, чтобы получить имя, которое было только что связано с сокетом, и выводим результат.

Если мы запустим программу в Solaris, то получим следующие результаты:

solaris % <b>umask</b> <i>сначала выводим наше значение umask</i>

022             <i>оно отображается в восьмеричной системе</i>

solaris % <b>unixbind /tmp/moose</b>

bound name = /tmp/moose, returned len = 13

solaris % <b>unixbind /tmp/moose</b> <i>снова запускаем программу</i>

bound name = /tmp/moose, returned len = 13

solaris % <b>ls -l /tmp/moose</b>

srwxr-xr-x 1 andy staff 0 Aug 10 13:13 /tmp/moose

solaris % <b>ls -lF /tmp/foo.bar</b>

srwxr-xr-x 1 andy staff 0 Aug 10 13:13 /tmp/moose=

Сначала мы выводим наше значение umask, поскольку в POSIX указано, что права доступа к создаваемому объекту определяются этим значением. Наше значение 022 выключает биты, разрешающие запись в файл для пользователей из группы (group-write) и прочих пользователей (other-write). Затем мы запускаем программу и видим, что длина, возвращаемая функцией getsockname, равна 13: один байт для элемента sun_len, один байт для элемента sun_family и 11 байт для полного имени (исключая завершающий нуль). Это пример аргумента типа «значение-результат», значение которого при завершении функции отличается от значения при вызове функции. Мы можем вывести полное имя, используя спецификатор формата %s функции printf, поскольку полное имя, хранящееся в sun_path, представляет собой завершающуюся нулем строку. Затем мы снова запускаем программу, чтобы проверить, что вызов функции unlink удаляет соответствующий файл.

Мы запускаем команду ls -l, чтобы увидеть биты разрешения для файла и тип файла. В Solaris (и большинстве версий Unix) тип файла — это сокет, что обозначается символом s. Мы также замечаем, что все девять битов разрешения включены, так как Solaris не изменяет принятые по умолчанию биты разрешения на наше значение umask. Наконец, мы снова запускаем ls с параметром -F, что заставляет Solaris добавить знак равенства (соответствующий типу «сокет») к полному имени.

ПРИМЕЧАНИЕ

Изначально значение umask не действовало на создаваемые процессами доменные сокеты Unix, но с течением времени производители исправили это упущение, чтобы устанавливаемые разрешения соответствовали ожиданиям разработчиков. Тем не менее все еще существуют системы, в которых разрешения доменного сокета могут не зависеть от значения umask. В других системах сокеты могут отображаться как каналы (символ р), а значок равенства при вызове ls -F может не отображаться вовсе. Однако поведение, демонстрируемое в нашем примере, является наиболее типичным.

15.3. Функция socketpair

Функция socketpair создает два сокета, которые затем соединяются друг с другом. Эта функция применяется только к доменным сокетам Unix.

#include &lt;sys/socket.h&gt;

int socketpair(int <i>family</i>, int <i>type</i>, int <i>protocol</i>, int <i>sockfd</i>[2]);

<i>Возвращает: ненулевое значение в случае успешного выполнения, -1 в случае ошибки</i>

Аргумент family должен быть равен AF_LOCAL, а аргумент protocol должен быть нулевым. Однако аргумент type может быть равен как SOCK_STREAM, так и SOCK_DGRAM. Два дескриптора сокета создаются и возвращаются как sockfd[0] и sockfd[1].

ПРИМЕЧАНИЕ

Эта функция аналогична функции Unix pipe: при ее вызове возвращаются два дескриптора, причем каждый дескриптор соединен с другим. Действительно, в Беркли-реализации внутреннее устройство функции pipe полностью аналогично функции socketpair [112, с. 253-254].

Два созданных сокета не имеют имен. Это значит, что не было неявного вызова функции bind.

Результат выполнения функции socketpair с аргументом type, равным SOCK_STREAM, называется потоковым каналом (stream pipe). Потоковый канал является аналогом обычного канала Unix (который создается функцией pipe), но он двусторонний, что позволяет использовать оба дескриптора и для чтения, и для записи. Потоковый канал, созданный функцией socketpair, изображен на рис. 15.1.

ПРИМЕЧАНИЕ

POSIX не требует поддержки двусторонних каналов. В SVR4 функция pipe возвращает два двусторонних дескриптора, в то время как ядра, происходящие от Беркли, традиционно возвращают односторонние дескрипторы (см. рис. 17.31 [112]).

15.4. Функции сокетов

Функции сокетов применяются к доменным сокетам Unix с учетом некоторых особенностей и ограничений. Далее мы перечисляем требования POSIX, указывая, где они применимы. Отметим, что на сегодняшний день не все реализации соответствуют этим требованиям.

1. Права доступа к файлу по умолчанию для полного имени, созданного функцией bind, задаются значением 0777 (чтение, запись и выполнение данного файла разрешены владельцу файла, группе пользователей, в которую он входит, и всем остальным пользователям) и могут быть изменены в соответствии с текущим значением umask.

2. Имя, связанное с доменным сокетом Unix, должно быть абсолютным, а не относительным именем. Причина, по которой нужно избегать относительного имени, в том, что в таком случае разрешение имени зависит от текущего рабочего каталога вызывающего процесса. То есть если сервер связывается с относительным именем, клиент должен находиться в том же каталоге, что и сервер (или должен знать этот каталог), для того чтобы вызов клиентом функции connect или sendto был успешным.


Перейти на страницу:
Изменить размер шрифта: