18 printf("bound name = %s, returned len = %d\n", addr2.sun_path, len);
19 exit(0);
20 }
Удаление файла
11
Полное имя, которое функция
bind
должна связать с сокетом, — это аргумент командной строки. Если это полное имя уже существует в файловой системе, при выполнении функции
bind
возникает ошибка. Следовательно, мы вызываем функцию
unlink
, чтобы удалить файл в том случае, если он уже существует. Если его не существует, функция
unlink
возвращает ошибку, которую мы игнорируем.
Вызов функций bind и getsockname
12-18
Мы копируем аргумент командной строки, используя функцию
strncpy
, чтобы избежать переполнения структуры, если полное имя слишком длинное. Поскольку мы инициализируем структуру нулем и затем вычитаем единицу из размера массива
sun_path
, мы знаем, что полное имя оканчивается нулем. Далее вызывается функция
bind
и мы используем макрос
SUN_LEN
для вычисления длины аргумента функции. Затем мы вызываем функцию
getsockname
, чтобы получить имя, которое было только что связано с сокетом, и выводим результат.
Если мы запустим программу в Solaris, то получим следующие результаты:
solaris % umaskсначала выводим наше значение umask
022 оно отображается в восьмеричной системе
solaris % unixbind /tmp/moose
bound name = /tmp/moose, returned len = 13
solaris % unixbind /tmp/mooseснова запускаем программу
bound name = /tmp/moose, returned len = 13
solaris % ls -l /tmp/moose
srwxr-xr-x 1 andy staff 0 Aug 10 13:13 /tmp/moose
solaris % ls -lF /tmp/foo.bar
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 <sys/socket.h>
int socketpair(int family, int type, int protocol, int sockfd[2]);
Возвращает: ненулевое значение в случае успешного выполнения, -1 в случае ошибки
Аргумент
family
должен быть равен
AF_LOCAL
, а аргумент
protocol
должен быть нулевым. Однако аргумент type может быть равен как
SOCK_STREAM
, так и
SOCK_DGRAM
. Два дескриптора сокета создаются и возвращаются как
sockfd[0]
и
sockfd[1]
.
ПРИМЕЧАНИЕ
Эта функция аналогична функции Unix pipe: при ее вызове возвращаются два дескриптора, причем каждый дескриптор соединен с другим. Действительно, в Беркли-реализации внутреннее устройство функции pipe полностью аналогично функции socketpair [112, с. 253-254].