Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Сокеты "AF_UNIX" - проблема с обратным направлением.  (Прочитано 14567 раз)
0 Пользователей и 1 Гость смотрят эту тему.
SaiborEye
Гость
« : 29-08-2008 09:32 » 

Задача под Линукс следующая: приложение-демон в момент запуска должно проверять наличие своей уже запущенной копии в памяти и выполнять действие в зависимости от результата (выдавать предупреждение и выгружаться, или передавать параметры работающей копии).
Для взаимодействия я выбрал сокеты типа AF_UNIX. Алгоритм следующий: в момент запуска программа выполняет следующий код:
Цитата
addr.sa_family = AF_UNIX;
strcpy(addr.sa_data,"/tmp/a1");// Имя приемного сокета
unlink("/tmp/a1");// Удаляем, если есть связанный файл
s1 = socket(AF_UNIX, SOCK_DGRAM, 0);// создаем датаграмный сокет для приема ответа
bind(s1, &addr, sizeof(addr));.// привязываем к нему имя

addr.sa_family = AF_UNIX;
strcpy(addr.sa_data,"/tmp/a2");// имя отправляющего сокета
s2 = socket(AF_UNIX, SOCK_DGRAM, 0);// создаем сокет для отправки запроса

sendto(s2, &request, sizeof(request), 0, &addr, sizeof(addr));// напрявляем запрос уже возможно работающей копии программы

FD_ZERO(&rfds);
FD_SET(s1,&rfds);
tv.tv_sec = 2;tv.tv_usec = 0;// Подготавливаем структуры для функции select приемного сокета
retval = select(1, &rdfs, NULL, NULL, &tv);// ждем 2 секунды ответа на ранее отправленный запрос
if(retval)recvfrom(s1, &reply, sizeof(reply), 0, NULL, NULL);// Принимаем ответ, если он пришел
else ...
.................

 получив положительный ответ, вызывает "exit" и завершается. Иначе, создает fork'ом новый процесс, содержащий функцию ответа и остается в памяти.

Функция ответа построена аналогично, только без использования select, блокируясь на recvfrom до получения запроса и сразу же выдает ответ через sendto. Запускается в новом процессе после отрицательного ответа вышеприведенного кода.

Все работает до получения ответа (select/recvfrom). Функция ответа получает запрос от вышеприведенного кода и отправляет ответ. В чем проблема, непонятно. Т.е. sendto отвечающей функции, ранее запущенной копии, выполняется, возвращает количество отправленных байт (их всего 8), но select из фрагмента выше вновь запущенной копии всегда завершается по таймауту (2 секунды) без указания на пришедшие данные. Может быть select вообще не работает с сокетами домена UNIX? И еще, выполнение close() сразу после sendto может уничтожить отправляемые данные, или они все-таки дойдут до адресата? (функция fflush на сокетах данного типа не поддерживается, вызывая segmentation fault).
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 29-08-2008 10:07 » 

SaiborEye, select то работает... Доку надо внимательно читать. Прочти в мане еще раз: что передается в select первым параметром?

Не по теме, а о цели задачи: в unix, обычно, для таких целей используют pid-файлы.

1. Открываешь такой файл на чтение. Если ошибка (проверить, что не связано с правами) - значит файла нет. Тогда п.6
2. Блокируем его (flock).
3. Читаем одну строку и пытаемся ее интерпретировать как число.
4. Проверяем по этому числу наличие такого процесса. Если его нет, то закрываем файл и переходим на п.6
5. Закрываем файл и выходим из программы.
6. Удаляем файл (без проверки ошибок), создаем файл, блокируем, пишем в него свой PID, закрываем.
7. Работаем в нормальном режиме.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
McZim
Команда клуба

ru
Offline Offline
Пол: Мужской
Я странный


WWW
« Ответ #2 : 29-08-2008 10:10 » 

SaiborEye, я так понимаю это все выполняется локально на одной машине? Тогда почему не воспользоваться средствами IPC?
Записан

The CBO without stats is like a morning without coffee. (c) T.Kyte.
SaiborEye
Гость
« Ответ #3 : 31-08-2008 03:28 » 

SaiborEye, select то работает... Доку надо внимательно читать. Прочти в мане еще раз: что передается в select первым параметром?

Не по теме, а о цели задачи: в unix, обычно, для таких целей используют pid-файлы.

1. Открываешь такой файл на чтение. Если ошибка (проверить, что не связано с правами) - значит файла нет. Тогда п.6
2. Блокируем его (flock).
3. Читаем одну строку и пытаемся ее интерпретировать как число.
4. Проверяем по этому числу наличие такого процесса. Если его нет, то закрываем файл и переходим на п.6
5. Закрываем файл и выходим из программы.
6. Удаляем файл (без проверки ошибок), создаем файл, блокируем, пишем в него свой PID, закрываем.
7. Работаем в нормальном режиме.

"ман" утверждает следующее: n на единицу больше самого большого номера дескриптора из всех наборов. Я эту фразу понимаю так: у меня один набор (rdfs), в нем один дескриптор, его номер "0", т.е. я передаю select'у единицу. "n" получается количество дескрипторов в самом длинном наборе из трех, передаваемых в функцию... Вроде все правильно.

Я бы использовал и PID файл, т.е. проблема конечно решаема другим путем, но меня задело, что такая простая вещь не работает.
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 31-08-2008 10:15 » 

SaiborEye, учи матчасть!

Номер дескриптора - это целое число! Соотв., первым параметром надо передать число, на единицу большее максимального значения среди дескрипторов, включенных в любой из трех наборов. В твоем случае это равно (s1 + 1). Если не хочешь высчитывать это значение, то тупо передай FD_SETSIZE (но не рекомендую).

Рекомендую книги W. Richard Stevens (У. Р. Стивенс):
1. UNIX Network Programming Volume2: Interproccess Communications (UNIX: взаимодействие процессов) - IBSN 0130810819 (русское издание - 5-318-00534-9)
2. UNIX Network Programming Networking APIs (UNIX: разработка сетевых приложений) - ISBN 013490012X (русское издание - 5-318-00535-7)

Книги это толстые и не для обучения, но написаны очень хорошо: разъясняются многочисленные нюансы, в каждом разделе есть работоспособные примеры с подробным описанием.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
SaiborEye
Гость
« Ответ #5 : 31-08-2008 14:41 » 

SaiborEye, учи матчасть!

Номер дескриптора - это целое число! Соотв., первым параметром надо передать число, на единицу большее максимального значения среди дескрипторов, включенных в любой из трех наборов. В твоем случае это равно (s1 + 1). Если не хочешь высчитывать это значение, то тупо передай FD_SETSIZE (но не рекомендую).

Рекомендую книги W. Richard Stevens (У. Р. Стивенс):
1. UNIX Network Programming Volume2: Interproccess Communications (UNIX: взаимодействие процессов) - IBSN 0130810819 (русское издание - 5-318-00534-9)
2. UNIX Network Programming Networking APIs (UNIX: разработка сетевых приложений) - ISBN 013490012X (русское издание - 5-318-00535-7)

Книги это толстые и не для обучения, но написаны очень хорошо: разъясняются многочисленные нюансы, в каждом разделе есть работоспособные примеры с подробным описанием.


Мда... А я полагал, что "номер" и "значение", это разные вещи... Теперь буду знать. Спасибо.
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 31-08-2008 20:04 » 

SaiborEye, если тип числовой, но смысл значения разве не номер?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
SaiborEye
Гость
« Ответ #7 : 01-09-2008 12:04 » 

SaiborEye, если тип числовой, но смысл значения разве не номер?

Ну если это массив чисел, то могут быть кроме их значений еще и их номера(индексы) в массиве. Я это имел ввиду.
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 01-09-2008 12:35 » 

SaiborEye, понятно. Все же посмотри в сторону книг, что я привел выше. Что-то есть в сети, но на английском. В бумажном виде есть русскоязычные издания.

На чем остановился? Pid-файлы?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
SaiborEye
Гость
« Ответ #9 : 02-09-2008 03:46 » 

SaiborEye, понятно. Все же посмотри в сторону книг, что я привел выше. Что-то есть в сети, но на английском. В бумажном виде есть русскоязычные издания.

На чем остановился? Pid-файлы?

Книги поищу, еще может пригодятся.
Теперь сокеты заработали как надо, поэтому наверное от них отказываться не буду, хотя в них не нравится то, что они привязаны к файловой системе (создают фиктивные файлы). Кроме определения присутствия работающей программы, я еще планирую передавать ей параметры через ее повторный запуск, и сокеты как раз подходят для этой цели.
Записан
SaiborEye
Гость
« Ответ #10 : 02-09-2008 03:57 » 

SaiborEye, я так понимаю это все выполняется локально на одной машине? Тогда почему не воспользоваться средствами IPC?
Я подумывал об этом, но пока решил остановиться на сокетах, в данном случае, AF_UNIX, тоже неплохо позволяющих осуществлять межпроцессное взаимодействие более знакомых мне из прошлого (Windows).
Записан
McZim
Команда клуба

ru
Offline Offline
Пол: Мужской
Я странный


WWW
« Ответ #11 : 02-09-2008 06:43 » 

хозяин барин Улыбаюсь
Записан

The CBO without stats is like a morning without coffee. (c) T.Kyte.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #12 : 03-09-2008 22:04 » 

UNIX-сокеты, вообще, вещь хорошая. Например через них можно передать между процессами дескриптор открытого файла. Никакой другой механизм (кроме fork()) не позволяет это делать. Кроме того, UNIX-сокеты могут быть не только замапированые на файловую систему, но и анонимные.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines