Добрый день!Столкнулся с трудностями с реализацией UDP-сервера, запускаемого из xinet.d. Задача элементарная: я с одной сетевой машины ("клиента") запускаю простенькую программку, она отправляет пакет на другую машину-сервер по определённому порту, слушаемому xinet.d, после чего происходит вызов моей программы-"сервера".
И если с протоколом TCP всё было ясно (смотрел вывод stdin и записывал его по fgets() в некоторый <char buffer[256]>), то у UDP всё гораздо серьёзнее. Запускаю на удалённой машине такой же простенький "клиент", он отдаёт сообщение на "сервер", моя программа-"сервер" запускается, но из stdin'а я абсолютно ничего не получаю. Нашёл в книжке такой пример ("Запуск приложения через inetd"). Здесь используется не вывод stdin, а следующая конструкция:
pid = sprintf(buf, "%d: ", getpid());
len = sizeof(peer);
rc = recvfrom(0, buf+pid, sizeof(buf)-pid, 0, (struct sockaddr*)&peer, &len);Попробовал её, но и здесь результат - нулевой. Конфигурация конф. файла xinet.d такова:
service my_server
{
disable = no
socket_type = dgram
flags = REUSE
instances = 1
wait = yes
protocol = udp
user = root
server = /tmp/Server/my_server
bind = 192.168.0.3
log_on_success = HOST PID
log_on_failure = HOST
}Вот фрагменты моего "клиента":
// в этой функции заполняю структуру адресов
static void set_address(char *, char *, struct sockaddr_in *, char *);
int main(int argc, char** argv)
{
const int on = 1;
int ident;
unsigned char* buffer = (unsigned char*) malloc(256);
struct sockaddr_in local;
struct sockaddr_in peer;
int s, s1, s2;set_address(PEER_ADDRESS, PEER_PORT, &peer, "udp");
set_address(LOCAL_ADDRESS, LOCAL_PORT, &local, "udp");srandom(time(NULL));
s = socket(PF_INET, SOCK_DGRAM, 0);
if (s<0) {printf("\nошибка вызова сокета\n");}
if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
{
printf("\nошибка вызова setsockopt\n");
exit(-1);
}if (bind(s, (struct sockaddr *) &local, sizeof(local)))
{
printf("\nошибка вызова функции bind\n");
printf(strerror(errno));
printf("\n");
exit(-1);
}......
// Я так понял, что данная функция возможна, но не обязательна//s1 = connect (s, (struct sockaddr*) &peer, sizeof(peer));
//if (s1 < 0){printf("\nошибка вызова функции connect()\n"); exit(-1);}
// В буфер вставлены некоторые значенияs2 = sendto(s, buffer, sizeof(buffer), 0,(struct sockaddr*) &peer, sizeof(struct sockaddr_in) );
}
Не могли бы вы мне помочь - подсказать, как это всё на самом деле реализуется?
Проблема снята. На всякий случай привожу здесь результаты.Для UDP всё решается путём введения функции следующего вида:
recvfrom(0, buffer, sizeof (buffer), 0, (struct sockaddr *)&peer, (socklen_t*)&len),где 0 - нулевой идентификатор ("как бы" сокета)
peer - указатель на структуру sockaddr_in
buffer - строковый массив
len - преобразованный численный размер структуры peerТогда, действительно, считываются данные, пришедшие на открытый сокет udp супер-сервера xinet.d.
>где 0 - нулевой идентификатор ("как бы" сокета)Не "как бы", а самый что ни на есть настоящий сокет. Просто inetd передаёт его дочернему процессу (Вашему демону) в виде нулевого файлового дескриптора: man dup2(2). Кстати, в случае с TCP происходит абсолютно то же самое, а read(fd, buf, len) в данном случае, если я не ошибаюсь, полностью идентично вызову recv(fd, buf, len, 0).