Выбрать главу

При работе в локальном пространстве имен допускается только протокол с номером 0.

Локальный сокет является частью файловой системы, поэтому он отображается командой ls (обратите внимание на букву s в строке режима):

% ls -l /tmp/socket

srwxrwx--x 1 user group 0 Nov 13 19:16 /tmp/socket

Если локальный сокет больше не нужен, его файл можно удалить с помощью функции unlink().

5.5.5. Примеры программ, работающих с локальными сокетами

Работу с локальными сокетами мы проиллюстрируем двумя программами. Первая (листинг 5.10) — это сервер. Он создает локальный сокет и переходит в режим ожидания запросов на подключение. Приняв запрос, сервер читает сообщения из сокета и отображает на на экране, пока соединение не будет закрыто. Если поступает сообщение "quit", сервер удаляет сокет и завершает свою работу. Программа socket-server ожидает путевое имя сокета в командной строке.

Листинг 5.10. (socket-server.c) Сервер локального сокета

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/socket.h>

#include <sys/un.h>

#include <unistd.h>

/* Чтение сообщений из сокета и вывод их на экран. Функция

   продолжает работу до тех пор, пока сокет не будет закрыт.

   Функция возвращает 0, если клиент послал сообщение "quit",

   в противном случае возвращается ненулевое значение. */

int server(int client_socket) {

 while (1) {

  int length;

  char* text;

  /* Сначала читаем строку, в которой записана длина сообщения.

     Если возвращается 0, клиент закрыл соединение. */

  if (read(client_socket, &length, sizeof(length)) == 0)

   return 0;

  /* Выделение буфера для хранения текста. */

  text = (char*)malloc(length);

  /* Чтение самого сообщения и вывод его на экран. */

  read(client_socket, text, length);

  printf("%s\n", text);

  /* Очистка буфера. */

  free(text);

  /* Если клиент послал сообщение "quit.", работа сервера

     завершается. */

  if (!strcmp(text, "quit"))

   return 1;

 }

}

int main(int argc, char* const argv[]) {

 const char* const socket_name = argv[1];

 int socket_fd;

 struct sockaddr_un name;

 int client_sent_quit_message;

 /* Создание локального сокета. */

 socket_fd = socket(PF_LOCAL, SOCK_STREAM, 0);

 /* Переход в режим сервера. */

 name.sun_family = AF_LOCAL;

 strcpy(name.sun_path, socket_name);

 bind(socket_fd, SUN_LEN(&name));

 /* Ожидание запросов. */

 listen(socket_fd, 5);

 /* Непрерывный прием запросов на подключение. Для каждого

    клиента вызывается функция server(). Цикл продолжается,

    пока не будет получено сообщение "quit". */

 do {

  struct sockaddr_un client_name;

  socklen_t client_name_len;

  int client_socket_fd;

  /* Прием запроса. */

  client_socket_fd =

   accept(socket_fd, &client_name, &client_name_len);

  /* Обработка запроса. */

  client_sent_quit_message = server(client_socket_fd);

  /* Закрытие серверной стороны соединения. */

  close(client_socket_fd);

 } while(!client_sent_quit_message);

 /* Удаление файла локального сокета. */

 close(socket_fd);

 unlink(socket_name);

 return 0;

}

Клиентская программа, показанная в листинге 5.11, подключается к локальному сокету и посылает сообщение. Путевое имя сокета и текст сообщения задаются в командной строке.

Листинг 5.11. (socket-client.c) Клиент локального сокета

#include <stdio.h>

#include <string.h>

#include <sys/socket.h>

#include <sys/un.h>

#include <unistd.h>

/* Запись строки TEXT в сокет, заданный