Программирование >>  Структура ядра и системные вызовы 

1 ... 66 67 68 [ 69 ] 70 71 72 ... 98


sp - new tli( argv[2J, argv[l] ); else sp = new tli (port);

if (!sp II lsp->good()) (

cerr server: create transport endpoint object failsNn ; return 1;

/* присвоить имя конечной точке транспортировки сервера */ if (sp->Bind() < 0) {

cerr server: bind fails\n ;

return 2;

for (struct t call *call=0; sp->listen(call)==0; ) (

/* принять запрос на соединение, поступивший от клиента */ if ((nsid = sp->accept(call)) < 0)

cerr server: accept fail,\n ; return 3;

) . hXjJC-

t free((char*)call, T CALL); освободить память

cerr server.; got one client ccmnection. nsid= nsid \n ; /* создать порожденный процесс для обработки команд */ process cmd(sp,nsid) ;

close(nsid); /* re-cycle file descriptor */

sp->shutdown(); return 0;

Эта серверная программа вызывается с целочисленным адресом - для установления локального соединения или с именем сервиса и хоста - для установления Internet-соединения. Сервер начинает работу с создания конечной точки транспортировки и присвоения ей имени. Затем он входит в цикл и ожидает поступления запросов на соединение от клиентских процессов (вызывая для этого функцию tli::listen).

Для каждого полученного запроса на соединение сервер вызывает функцию tlir.accept, которая устанавливает соединение с клиентской конечной точкой транспортировки. Эта функция возвращает также новый дескриптор {nsid) для того, чтобы дать возможность серверу взаимодействовать с клиентом, соединение с которым было установлено с ее помощью. Для обработки команд данного клиента сервер вызывает функцию process cmd. Функция process cmd, в свою очередь, создает для работы с клиентом порожденный

процесс. Сразу же после этого она возвращает управление серверному процессу, чтобы сервер мог продолжать мониторинг других запросов на соединение.

Каждый порожденный процесс, созданный функцией process cmd, вызывает функцию tii::read, которая читает команды клиента, установивщего соединение, и посьшает ответы с помощью функции tii::write. Если клиент посылает в этот порожденный процесс команду QUIT CMD, процесс разрывает соединение посредством вызова функции (И:.shutdown и завершается.

Ниже приведена клиентская программа tlimsgcls.C, обеспечивающая взаимодействие с программой-сервером путем использования объектов класса ТЫ:

♦include tli.h ♦define QUIT CMD 2

int main( int argc, char* argvtJ) (

if (argc < 2) {

cerr usage: argv[01 <serviceno> [<host>l\n ; return 1;

char buf[80];

int port=-l, rc, flags;

/* проверить, указан ли Целочисленный адрес иЛи имя сервиса */ (void)sscanf(argv[l), %d ,fiport);

tli *sp;

if (port==-l)

sp = new tli( argv[2], argv[l] ); else sp = new tli (port);

if (!sp 11 !sp->good()) [

cerr client: create transport endpoint object fails\n ; return 1;

>.

if (sp->Bind anonyinous 0 < 0) [

cerr client: bind fails\n ; return 2;

/* установить соединение с конечной точкой сервера */ if (sp->cpnnectО < 0) {

. cerr client: connect failsXn ; return 3;

/* послать серверу команды О - i*.*



for (int cmd=0; cmd < 3; cmd++)

/* сформировать команду для сервера */ sprintf(buf, %d ,cmd);

if (sp->write(buf,strlen(buf)+1) < 0) return 4;

/* выйти из цикла, если QUIT CMD */ if (cmd= =QUIT CMD) break;

/* прочитать ответ сервера *,/

if (sp->read(buf,sizeof buf, flags) < 0) return 5; cerr client: recv buf \n ;

sp->shutdown(); return 0;

Эта программа-клиент вызывается с адресом сервера, значение которого может быть целым числом в случае локального соединения или именем сервиса и хоста при установлении Internet-соединения. Клиент начинает работу с создания конечной точки транспортировки и присвоения ей имени anonymous. Клиент не обязан присваивать точке конкретное имя, потому что ни один другой процесс не должен инициировать запрос на соединение по указанному адресу с серверным процессом.

После создания конечной точки транспортировки клиент вызывает функцию tli.xonnect, которая создает соединение типа виртуальный канал с серверной конечной точкой транспортировки. Если данная операция выполняется нормально, клиент посылает серверу ряд команд (посредством вызовов функции tli::write). Команды могут быть такими: L0CAL TIME, UTC TIME и QUIT CMD. Передав очередную команду (это не относится к команде QUIT CMD), клиент ожидает ответа сервера (для чего вызывает функцию tlir.read) и направляет его ответное сообщение на стандартный вывод.

После передачи серверу команды QUIT CMD клиент разрывает соединение посредством вызова функции tlir.shutdown, а затем завершает работу. Результат взаимодействия описанных программ представлен ниже:

% СС -о tli msg srv tli msg srv.C -Insl % СС -о tli msg cls tli msg cls.С -Insl % tli msg srv 2 & [1] 781

server: t bind: 2

% tli msg cls 2

client: connect to addr=2

server: got one client connection. nsid=4

server: read cmd: 0

client: recv Fri Feb 17 22:34:50 1997*: server: read cmd 1

client: recv Sat Feb 18 06:34:50 1997.

server: read cmd: 2*

[1] + Done tli msg srv 2

Обе эти программы способны устанавливать соединение по сети Intemet, причем никакая их доработка не требуется. Для того чтобы указанные программы можно было выполнять, достаточно ввести в файл /etc/services новую запись:

test 4045/tcp

Посредством этой записи организуется сервис с именем test, который использует в качестве провайдера транспорта протокол TCP. Этому сервису назначен порт номер 4045. Ниже приведены результаты выполнения этих же программ, но с указанием адреса хост-имени fivit и имени сервиса test.

% hiostname fruit

% tli msg srv test fruit & [1] 776

server: t bind: 135122

% tli msg cls test fruit

client: connect to addr=135122

server: got one client connection. nsid=4

server: read cmd: 0

client: recv Fri Feb 17 29:34:50 1997 server: read cmd: 1

client: recv Sat Feb 18 09:34:50 1997

server: read cmd: 2

[1] + Done tli msg srv test fruit

11.7. Пример взаимодействия процессов с помощью дейтаграмм

Далее рассмотрим два одноранговых процесса, взаимодействующих через две конечные точки транспортировки, использующие для обмена сообщениями дейтаграммы. Эти программы - Ш сШ1 и tli clts2 - созданы соответственно из исходных файлов т сШ1.Ск tli clts2.C.

Вот текст программы tlijcltsl.C:

♦include <sys/systeminfo.h> ♦include tli.h

♦define MSGl Hello MSGl from cltsl /* получить имя хоста */

int gethost( int argc, char* argv[], char host[], int len)

if (argc!=3) (

if (sysinfo(SI HOSTNAME,host,len)< 0) {



perror< sysinfo ) ; return -1;

else strcpy(host,argv(2]) ; return 0;

int main( int argc, char* argv[])

( , ,. . ...J. ,

char buf[80), host(80); int port=-l, rc, flags=0;

if (argc < 2) {

cerr usage: argv(O) <serviceIport no>

(<hostname>]\n ;

return 1;

/* проверить, указан ли номер порта */ (void)sscanf(argv[l], %d ,sport); ,

tli *sp;

if (port==-l) {

if (gethost(argc, argv, host, sizeof host) < 0) return 2;

sp = new tli( host, argv(l], 1 ); ) else sp = new tli (port, 1);

if (!sp II !sp->good()) (

cerr cltsl: cjreate transport endpoint object failsXn ; return 3;

/* присвоить имя конечной точке транспортировки */ 1£ (sp->Bind() < 0) {

cerr cltsl: bind failsXn ;

return 4;

struct t unitdata *ud = 0;

if (sp->readfrom( buf, sizeof buf, flags, ud) < 0)

cerr cltsl: readfrom failsXn ; return 5;

cerr cltsl: read msg: buf Xn ;

if (sp->writeto(MSGl, strlen(MSGl)+1, flags, ud) < 0) (

cerr cltsl: writeto fails\n*VF return 6;

if (sp->readfrom(buf, sizeof buf, flags, ud) < 0) (

cerr cits: readfrom failsXn ; return 7;

cerr cltsl: read msg: buf Xn ; return 0;

Программа tli cltsl может вызываться с одним адресом, значение которого является целым числом (в случае установления локального соединения) или с именем сервиса и необязательным хост-именем (при использованрш Intemet-соединения). Если указывается имя сервиса, оно должно быть занесено в файл /etc/services. Если хост-имя одновременно с именем сервиса не указывается, в качестве такового подразумевается хост-имя машины, на которой выполняется рассматриваемая программа.

Работа программы tlicltsl начинается с создания объекта TLI (конечной точки транспортировки) по заданным аргументам командной строки. Если необходимо создать конечную точку транспортировки для Internet, то вызывается функция gethost, которая выявляет хост-имя локальной машины в аргументе командной строки (если он есть) Риги посредством вызова функции sysinfo.

После создания конечной точки ТЫ и присвоения ей имени процесс читает сообщение (MSG2), посланное ему процессом tli clts2. Получив сообщение MSG2, процесс направляет его на стандартный вывод. Затем он посылает в процесс /c/toi сообщение MSG1, пользуясь адресом, содержащимся в переменной ud. Значение этой переменной присваивается посредством вызова функции readfrom.

Наконец, процесс ждет, когда tli clts2 пошлет последнее сообщение, MSG3. Получив данное сообщение, процесс направляет его на стандартный вывод и завершается. Конечная точка транспортировки, созданная процессом, уничтожается функцией-деструктором ТЫ::~ТЫ.

Ниже приведена программа tli clts2.C, которая взаимодействует с программой tlicltsl:

♦include <sys/systeminfо.h> ♦include tli.h

♦define MSG2 Hello MSG2 from clts2 ,

♦define MSG3 Hello MSG3 from clts2 :

typedef enum { LOCAL TIME, GMT TIME, QUIT CMD, ILLEGAL CMD ) CMOS;

/* получить имя хоста */

int gethost( int argc, char* argv[], char host{], int len)

if (argc!=4) (

if (sysinfo(SI HOSTNAME,host,len)< 0) (



1 ... 66 67 68 [ 69 ] 70 71 72 ... 98

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика