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

1 ... 63 64 65 [ 66 ] 67 68 69 ... 98


должно быть хфугих ожидающих обработки запросов на соединение,/Иначе вызов функции завершится неудачей. Во втором случае дескриптор newfd должен быть определен посредством вызова topen до использования в вызове данной функции. После успешного завершения вызова taccept аргумент fd можно использовать для обработки запросов на соединение от других клиентов, а newfd применяется исключительно для связи с клиентом, адрес которого задан значением call. Это значение было получено в результате вызова функции tjisten.

В случае успешного выполнения данная функция возвращает О, а в случае неудачи возвращает -1.

В следующем примере порождается процесс, который принимает запросы на соединение из одного или нескольких клиентских процессов. Обратите внимание на то, что конечная точка транспортировки, указанная аргументом fd, работает в блокирующем режиме:

struct t call *call = (struct t call*)t alloc(fd, T CALLOC, T ALL); if (icall)

t error( t alloc fails for T CALL ); else while (t listen (fd, call), == 0) /* получен олин запрос на

- j>r-j соединение */ switch (for)c()) ( , .1

сазе -1: perror( forl< 0? ЬгеаК/ /* родительский процесс; вызов

fozk завершился неудачно */ default: break; /* родительский процесс; вызов fork выполнен успешно */

case 0: /* порожденный процесс для связи с клиентом */

if (newfd=t open( /dev/ticotsord , 0 RDWR, 0))==-l M

t bind(newfd,0,0)== -1)

t error( T open or t bind fails ); else if (t accept(fd, newfd, call)==-l)

t error( t accept fails\n ); else {

t close(fd);

/* теперь - связь с клиентом посредством дескриптора newfd */

В этом примере сначала вызывается функция talloc, с помощью которой выделяется память под объект типа struct tcall, где будет храниться адрес клиента. Указателем на этот объект является переменная call. Если вызов t alloc выполняется успешно, то начинается цикл, в котором вызывается функция tjisten, итеративно проверяющая наличие запросов на соединение. Для каждого принятого запроса программа создает порожденный процесс, обеспечивающий взаимодействие с соответствующим клиентом. В частности, каждый порожденный процесс создает новую конечную точку транспортировки того типа, который задан аргументом fd. Эту новую точку обозначает переменная newfd, и ей присваивается имя, назначенное провайдером транспорта. После этого порожденный процесс вызывает функцию tjaccept, которая устанавливает соединение между конечной точкой, заданной

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

11.4.6. Функция t connect

Прототип функции tconnect выглядит следующим образом:

#include <tiuser.h>

int t connect ( int fd, struct t call* inaddr, struct t call* outaddr);

Эта функция посылает в серверную конечную точку транспортировки запрос на соединение. Аргумент fd показывает, какая клиентская конечная точка транспортировки должна быть соединена с конечной точкой сервера. Адрес сервера задается аргументом inaddr, а адрес серверной конечной точки транспортировки - аргументом outaddr.

Значение аргумента inaddr не должно быть равным NULL. Значение аргумента outaddr может быть равным NULL, если адрес сервера не имеет значения.

По умолчанию рассматриваемая функция блокирует вызывающий процесс до тех пор, пока не будет установлено соединение с серверной конечной точкой транспортировки или не произойдет системная ошибка. Если же точка fd задана как неблокирующая, то данная функция инициирует выдачу запроса на установление соединения и возвращает управление немедленно (при условии, что соединение с серверной конечной точкой транспортировки не было установлено сразу же). Глобальной переменной terrno присваивается значение TNODATA. Клиент может затем вызвать функцию t rcvconnect, чтобы проверить успешность выполнения запроса на соединение. Прототип функции trcvconnect:

#include <tiuser.h>

int t rcvconnect ( int fd, struct t call* outaddr);

В случае успешного выполнения эта функция возвращает О, а в случае неудачи возвращает -L

В следующем примере конечная точка транспортировки переводится в неблокирующий режим работы, для чего используется вызов функции fcntl. Затем эта конечная точка пытается соединиться с сервером в неблокирующем режиме. Адрес сервера принимается равным 3.

struct t call *call If (Icall) {

(struct t call*)t alloc(fd, T CALLOC, T ALL);



t error( t alloc fails for T CALL ); exit(l);

call->addr.len = sizeof (int); задать адрес сервера

*(int)call->addr.buf = 3; /* Установить fd как неблокирующий. Это можно сделать и при вь зовё t open */

if (flg=fcntl(fd; F GETFL, 0)==-l II

fcntl(fd, F SETFL, fig I O NONBL0CK)-1) ( perror( fcntl ); exit(2);

if (t oonnect (fd, call, oall)) -l) (

while (t errno == TNODATA) ( /* опросить на предмет завершения

запроса на соединение */

/* выполнить другие операции */

if (t rcvconneot (fd, call)=0) break;

, }

if (t errno != TNODATA) ;{ oTh

t error ( t connect or t rovoonne.ct fails ); exit (4) ; ., ...

} /* t connect */

/* начать взаимодействие с серверной конечной точкой транспортировки */

В этом примере сначала вызывается функция/сл , которая устанавливает неблокирующий режим работы для конечной точки транспортировки, указанной аргументом fd. Затем программа вызывает функцию tcomect, посредством которой устанавливается соединение с серверной конечной точкой транспортировки. Адрес сервера принимается равным 3 (только для локального соединения). Если / соллес? заверщается неудачно, программа входит в цикл, где выполняет другие операции, а затем вызывает функцию t rcvconnect для проверки успещности запроса на соединение. Цикл заверщается, когда t rcvconnect возвращает код успещного выполнения (возвращаемое значение равно нулю) или когда возникает ощибка и t errno не присваивается значение TNODATA. Если вызов функции tcomect или trcvconnect заверщается успешно, программа начинает взаимодействие с серверным процессом.

11.4.7. Функции t snd, t sndudata

Прототипы функций t snd и tjsndudata выглядят следующим образом:

#include <tiuser.h>

Int tjsnd ( int fd, char* buf, unsigned len, int flags ); int tjsndudata ( int fd, struct t unitdata* udata );

Функция t snd посылает сообщение длиной len байтов (которое содержится в буфере buf) в другой процесс, соединение с которым устанавливается через конечную точку транспортировки, указанную аргументом fd. Эта точка должна функционировать на основе виртуального канала и соединяться с другой конечной точкой посредством вызова tconnect (для клиентского процесса) или t accept (для серверного процесса).

Аргумент flags может иметь нулевое (по умолчанию) или одно из указанных ниже значений, которые определяются в заголовке <tiuser.h>.

Значение flags Смысл

Т EXPEDITED

Т MORE

Отмечает сообщение как срочное. Действует аналогично флагу MSG OOB в гнездах. Провайдер транспорта может поддерживать эту опщпо, а может и не поддерживать. В последнем случае функция возвращает код неудачного завершения и переменной t ermo присваивается значение TNOTSUPPORT

Сообщает процессу-получателю о том, что сообщение, которое будет передано при следующем вызове t snd, является продолжением текущего

В случае успеха рассматриваемая функция юзвращает число символов, помещенных в буфер buf которые переданы нормально, а в случае неудачи -1. Если дескриптор/й? задан как неблокирующий и сообщение, находящееся в buf невозможно доставить получателю сразу же, функция немедленно завершает свою работу. В этом случае возвращается значение -1 и переменной t errno присваивается значение TFLOW.

Функция t sndudata используется для передачи дейтаграммных сообщений через конечную точку транспортировки без установления соединения. Структура tunitdata объявляется следующим образом:

struct t unitdata {

struct netbuf addr; struct netbuf opt; struct netbuf udata;

Здесь структура udata содержит сообщение, подлежащее передаче в конечную точку транспортировки, ацрес которой указан в addr. Структура opt содержит зависящие от провайдера транспорта опции, используемые при доставке данного сообщения.

Отметим, что в вызове tsndudata нет аргумента flags, с помощью которого передаваемое сообщение определялось бы как срочное.

В случае успещного вьшолнения рассматриваемая функция возвращает О, а в случае неудачи возвращает -1. Если дескриптор fd задан как неблокирующий и если сообщение, находящееся в udata, невозможно доставить получателю сразу же, функция завершает свою работу немедленно. В этом случае возвращается -1 и переменной terrno присваивается значение TFLOW.



Далее срочное сообщение (MSG1) посылается в конечную точку транспортировки, с которой уже установлено соединение: /

char* MSGl = Hello World ;

if (t snd(MSGl, strlen(MSGl)+1, T EXPEDITED) < 0) t error( t sna );

A в этом примере дейтаграммное сообщение (MSGl) посылается в конечную точку транспортировки с адресом 3 (локальное соединение):

char* MSGl = Hello World ; struct t unitdata *t ud =

(struct t unitdata*)t alloc(fd, T UNITDATA, T ALL); if (!t ud) (

t error( t alloc for T UNITDATA fails );

exit(l);

t ud->addr.len = sizeof(int); установить адрес получателя */

* (int) t ud->addr .buf = 3; я--

t ud->udata.len = strlen(MSGl)+1; 7* указать сообщение, предназначенное для передачи */ t ud->udata.buf = MSGl;

if (t sndudata(fd, t ud) < 0) ,t error( t sndudata );

11.4.8. Функции t rcv, t rcvudata и t rcvuderr

Прототипы функций t rcv, t rcvudata и t rcvuderr выглядят следующим образом:

#include <tiuser.h>

int t rcv ( int fd, clia * buf, unsigned len, int* flags );

int tjrcvudata ( int fd. st uct t unitdata* udata, Int* flags );

int tjrcvuden ( int fd. st uct t ude * uderr );

Функция trcv принимает сообщение, помещенное в буфер *м/другим процессом, который соединен с транспортной конечной точкой, обозначенной аргументом fd. Эта точка должна быть виртуальным каналом и соединяться с другой конечной точкой посредством вызова t connect (для клиентского процесса) или t accept (для серверного процесса).

Значение len задает максимальный размер буфера buf Аргумент flags - это адрес целочисленной переменной. Данная переменная содержит значение flags, которое посылается вместе с сообщением при вызове функции t snd. Возможные значения, возвращаемые в flags- О, TMORE и/или T EXPEDITED (описаны в предьщущем разделе).

В случае успешного выполнения рассматриваемая функция возвращает число байтов данных, помещенных в buf а в случае неудачи -1. Если точка fd задана как неблокирующая и никакое сообщение не может быть принято тотчас же, функция немедленно завершает свою работу, возвращает -1 и переменная tjermo устанавливается в TNODATA.

Функция t rcvudata используется для приема дейтаграммных сообщений через конечную точку транспортировки, функционирующую в режиме без установления соединения. Значение udata - это адрес переменной типа struct unitdata, в которой содержится принятое дейтаграммное сообщение и адрес отправителя.

Аргумент flags содержит адрес целочисленной переменной, которой обычно присваивается значение 0. Если буфер udata->udata.buf слишком мал для приема всего сообщения, то значениеу/а; устанавливается в T MORE и ядро копирует ровно такую часть текста сообщения, какая может поместиться в буфере udata->udata.buf. Для приема оставшейся части сообщения процесс должен вызвать функцию t rcvudata еще раз.

В случае успешного выполнения эта функция возвращает О, а в случае неудачи -1. Если точка/rf задана как неблокирующая и никакое сообщение не может быть принято тотчас же, функция немедленно прекращает свою работу и возвращает -1; переменной t ermo присваивается значение TNODATA.

Функция trcvuderr используется для приема сообщений об ошибках, связанных с дейтаграммным сообщением. Ее следует вызывать только в том случае, если вызов tj-cv возвращает код неудачного завершения. Структура tuderr объявляется следующим образом:

struct t uderr (

struct netbuf addr; struct netbuf opt; long error;

Здесь переменная addr содержит адрес пункта назначения сообщения об ошибке, opt - это зависящие от провайдера транспорта параметры, используемые при доставке данного сообщения, а error - код ошибки.

Значение uderr может быть задано как NULL. Это означает, что диагностические сообщения об ошибках не нужны и функция просто сбрасывает внутренний флаг, сигнализирующий о наличии ошибки.

В случае успешного выполнения эта функция возвращает О, а в случае неудачи возвращает -1.

Ниже принимается сообщение из конечной точки транспортировки, с которой установлено соединение:

int flags; char buf[80);

If (t rcv(fd, buf, sizeof(buf), sflags) < 0) t error( t rcv );

A в этом примере принимается дейтаграммное сообщение из конечной точки транспортировки, предназначенной для однорангового соединения. Если вызов t rcvudata неудачен, выводится диагностическое сообщение об ошибке:

struct t unidata *t ud =

(struct t unidata*)t alloc(fd, T UNIDATA, T ALL);



1 ... 63 64 65 [ 66 ] 67 68 69 ... 98

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