Литмир - Электронная Библиотека
Содержание  
A
A
Вызов функций 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
был успешным.

168
{"b":"225366","o":1}