UNIX: разработка сетевых приложений
Часть 170 из 399 Информация о книге
7 sockfd = Socket(AF_LOCAL, SOCK_STREAM, 0);8 bzero(&servaddr, sizeof(servaddr));9 servaddr sun_family = AF_LOCAL;10 strcpy(servaddr.sun_path, UNIXSTR_PATH);11 Connect(sockfd, (SA*)&servaddr, sizeof(servaddr));12 str_cli(stdin, sockfd); /* выполняет всю работу */13 exit(0);14 }Теперь структурой адреса сокета, которая должна содержать адрес сервера, будет структура6.sockaddr_unПервый аргумент функции7—socket.AF_LOCALКод для заполнения структуры адреса сокета идентичен коду, показанному для сервера: инициализация структуры нулем, установка семейства протоколов8-10и копирование полного имени в элементAF_LOCAL.sun_pathФункция12— та же, что и раньше (в листинге 6.2 представлена последняя разработанная нами версия).str_cli15.6. Клиент и сервер дейтаграммного доменного протокола Unix
Теперь мы перепишем наши клиент и сервер UDP из разделов 8.3 и 8.5 с использованием сокетов. В листинге 15.5 показан сервер, который является модификацией листинга 8.1.
Листинг 15.5. Эхо-сервер дейтаграммного доменного протокола Unix
//unixdomain/unixdgserv01.c1 #include "unp.h"2 int3 main(int argc, char **argv)4 {5 int sockfd;6 struct sockaddr_un servaddr, cliaddr;7 sockfd = Socket(AF_LOCAL, SOCK_DGRAM, 0);8 unlink(UNIXDG_PATH);9 bzero(&servaddr, sizeof(servaddr));10 servaddr.sun_family = AF_LOCAL;11 strcpy(servaddr.sun_path, UNIXDG_PATH);12 Bind(sockfd, (SA*)&servaddr, sizeof(servaddr));13 dg_echo(sockfd, (SA*)&cliaddr, sizeof(cliaddr));14 }Две структуры адреса сокета относятся теперь к типу6.sockaddr_unДля создания дейтаграммного доменного сокета Unix первый аргумент функции7должен иметь значениеsocket.AF_LOCALКонстанта8-12определяется в заголовочном файлеUNIXDG_PATHкакunp.h. Сначала мы вызываем функцию/tmp/unix.dg, чтобы удалить полное имя в случае, если оно сохранилось после предыдущего запуска сервера, а затем инициализируем структуру адреса сокета перед вызовом функцииunlink. Ошибка при выполнении функцииbind— это нормальное явление.unlinkИспользуется та же функция13(см. листинг 8.2).dg_echoВ листинге 15.6 представлен эхо-клиент дейтаграммного доменного протокола Unix. Это модификация листинга 8.3.
Листинг 15.6. Эхо-клиент дейтаграммного доменного протокола Unix
//unixdomain/unixdgcli01.с1 #include "unp.h"2 int3 main(int argc, char **argv)4 {5 int sockfd;6 struct sockaddr_un cliaddr, servaddr;7 sockfd = Socket(AF_LOCAL, SOCK_DGRAM, 0);8 bzero(&cliaddr, sizeof(cliaddr)); /* связывание сокета с адресом */9 cliaddr.sun_family = AF_LOCAL;10 strcpy(cliaddr.sun_path, tmpnam(NULL);11 Bind(sockfd, (SA*)&cliaddr, sizeof(cliaddr));12 bzero(&servaddr, sizeof(servaddr)); /* заполняем структуру адресасокета сервера */13 servaddr.sun_family = AF_LOCAL;14 strcpy(servaddr.sun_path, UNIXDG_PATH);15 dg_cli(stdin, sockfd, (SA*)&servaddr, sizeof(servaddr));16 exit(0);17 }Структурой адреса сокета, содержащей адрес сервера, теперь будет структура6. Мы также размещаем в памяти одну из этих структур, чтобы она содержала адрес клиента, о чем мы расскажем далее.sockaddr_unПервый аргумент функции7— этоsocket.AF_LOCALВ отличие от клиента UDP при использовании дейтаграммного доменного протокола Unix требуется явно связать с помощью функции8-11полное имя с нашим сокетом, чтобы сервер имел полное имя, на которое он мог бы отправить свой ответ. Мы вызываем функциюbind, чтобы получить уникальное полное имя, с которым затем при помощи функцииtmpnamсвяжем наш сокет. Вспомните из раздела 15.4, что при отправке дейтаграммы на неприсоединенный дейтаграммный доменный сокет Unix не происходит неявного связывания полного имени с сокетом. Следовательно, если мы опустим этот шаг, вызов сервером функцииbindв функцииrecvfromвозвращает пустое полное имя, что затем приведет к ошибке, когда сервер вызовет функциюdg_echo.sendto