Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Назад Сервер TCP/IP ... много серверов хороших и разных Вперед

Сервер активируемый суперсервером (xinetd)

Прежде, чем переходить к потоковым реализациям, рассмотрим ещё один вариант этого класса, но в котором создание процесса fork() выполняется неявно: использование суперсервера xinetd. При этом весь сервис по запуску процессов-копий нашего приложения, и перенаправлению его стандартных потоков ввода-вывода в сетевой сокет возьмёт на себя xinetd. Вот полный текст ретранслирующего сервера для этого случая (файл ech3.cс):

#include "common.h"
static char data[ MAXLINE ];

int main( int argc, char *argv[] ) { 
   write( STDOUT_FILENO, data, read( STDIN_FILENO, data, MAXLINE ) ); 
   exit( EXIT_SUCCESS ); 
}; 

Просто? Мне кажется, что – очень. Но в расплату за простоту кода нам придётся повозиться с конфигурациями xinetd:

  • Дописываем в конфигурационный файл /etc/services строку, определяющую порт, через который будет вызываться приложение этого сервера:
  • ech3            51004/tcp
  • В каталоге конфигураций /etc/xinetd.d создадим файл конфигурации для этого сервера (имя файла значения не имеет, но для однозначности называем его ech3), заполняем его содержимое:
    $ cat /etc/xinetd.d/ech3 
    service ech3 
    { 
        disable = no 
        protocol = tcp 
        wait = no 
        user = olej 
        server = /home/olej/ech3 
    } 

    Здесь: server — абсолютное путевое имя файла сервера, куда мы его поместили; user — имя пользователя, от имени которого будет выполняться сервер после старта.

  • Суперсервер выполняется как сервис Linux. Запускаем или перезапускаем xinetd:

    # /etc/init.d/xinetd restart
    Restarting xinetd (via systemctl):  [ OK ]
    # ps -A | grep xinetd
    12507 ?  00:00:00 xinetd
  • Если после очередной правки конфигураций (показанных выше) нам нужно заставить xinetd перечитать новые конфигурации, то делаем это так:
    # kill -SIGHUP 12507
  • Проверяем правильность конфигураций и запуск по запросу нашего сервера ech3, например, локальным выполнением:
    $ telnet 127.0.0.1 51004 
    Trying 127.0.0.1... 
    Connected to 127.0.0.1. 
    Escape character is '^]'. 
    123 
    123 
    Connection closed by foreign host. 
    

    Или так:

    $  netstat -a | grep ech 
    tcp        0      0 *:echo                     *:*                         LISTEN      
    tcp        0      0 *:ech3                     *:*                         LISTEN      
    udp        0      0 *:echo                     *:*                                     
    

Теперь всё готово для проверки характеристик сервера:

$ ./cli -a 192.168.1.5 -p 51004 -n 20 
host: 192.168.1.5, TCP port = 51004, number of echoes = 20 
time of reply - Cycles [usec.] : 
12308646[4010] 11768571[3834]  11953054[3894]  13832637[4506]  12359648[4026] 
11718109[3817] 13003061[4236]  14025745[4569]  12321905[4014]  11671661[3802] 
11614506[3783] 11515571[3751]  11477414[3739]  11517457[3752]  15932227[5190] 
11998065[3908]  7625133[2484]   7460694[2430]   7524047[2451]   8133041[2649] 

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


Назад Сервер TCP/IP ... много серверов хороших и разных Вперед