URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 8143
[ Назад ]

Исходное сообщение
"UDP-сервер под xinetd"

Отправлено Lex Grant , 11-Мрт-09 18:27 
Добрый день!

Столкнулся с трудностями с реализацией 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-сервер под xinetd"
Отправлено Lex Grant , 12-Мрт-09 13:39 
Проблема снята. На всякий случай привожу здесь результаты.

Для UDP всё решается путём введения функции следующего вида:
recvfrom(0, buffer, sizeof (buffer), 0, (struct sockaddr *)&peer, (socklen_t*)&len),

где  0 - нулевой идентификатор ("как бы" сокета)
peer - указатель на структуру sockaddr_in
buffer - строковый массив
len - преобразованный численный размер структуры peer

Тогда, действительно, считываются данные, пришедшие на открытый сокет udp супер-сервера xinet.d.


"UDP-сервер под xinetd"
Отправлено jd2 , 16-Мрт-09 18:42 
>где  0 - нулевой идентификатор ("как бы" сокета)

Не "как бы", а самый что ни на есть настоящий сокет. Просто inetd передаёт его дочернему процессу (Вашему демону) в виде нулевого файлового дескриптора: man dup2(2). Кстати, в случае с TCP происходит абсолютно то же самое, а read(fd, buf, len) в данном случае, если я не ошибаюсь, полностью идентично вызову recv(fd, buf, len, 0).