Сервер принимает от клиента запрос на подключение, вызывая функцию accept()
. Первый ее аргумент — это дескриптор сокета. Второй аргумент указывает на адресную структуру, заполняемую адресом клиентского сокета. Третий аргумент содержит длину (в байтах) адресной структуры. Функция accept()
создает новый сокет для обслуживания клиентского соединения и возвращает его дескриптор. Исходный серверный сокет продолжает принимать запросы от клиентов. Чтобы прочитать данные из сокета, не удалив их из входящей очереди, воспользуйтесь функцией recv()
. Она принимает те же аргументы, что и функция read(), плюс дополнительный аргумент FLAGS
. Флаг MSG_PEEK
задает режим "неразрушающего" чтения, при котором прочитанные данные остаются в очереди.
5.5.4. Локальные сокеты
Сокеты, соединяющие процессы в пределах одного компьютера, работают в локальном пространстве имен (PF_LOCAL
или PF_UNIX
, это синонимы). Такие сокеты называются
Имя сокета задается в структуре типа sockaddr_un
. В поле sun_family
необходимо записать константу AF_LOCAL
, указывающую на то, что адрес находится в локальном пространстве имен. Поле sun_path
содержит путевое имя файла и не может превышать 108 байтов. Длина структуры sockaddr_un
вычисляется с помощью макроса SUN_LEN()
. Допускается любое имя файла, но процесс должен иметь право записи в каталог, где находится файл. При подключении к сокету процесс должен иметь право чтения файла. Несмотря на то что файловая система может экспортироваться через NFS на разные компьютеры, только процессам, работающим в пределах одного компьютера, разрешается взаимодействовать друг с другом посредством локальных сокетов.
При работе в локальном пространстве имен допускается только протокол с номером 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
ожидает путевое имя сокета в командной строке.
#include
#include
#include
#include
#include
#include
/* Чтение сообщений из сокета и вывод их на экран. Функция
продолжает работу до тех пор, пока сокет не будет закрыт.
Функция возвращает 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;
/* Создание локального сокета. */