|
Программирование >> Структура ядра и системные вызовы
if < t ud) < cr-.iVfv/ ft; t error( t alloc for T UNIDATAfails ); , exit (11; int flags; char buf[80]; t ud->tidata.len = sizeof(buf); /* организовать буфер для приема сообщения */ t ud->udata.buf = buf; if (t rcvudata(fd, t ud, Sflags) < 0) ( /* принять дейтаграммное сообщение */ if (t errno==TLOOK) ( struct t uderr *uderr = (struct t uderr*)t alloc(fd, T UDERROR, T ALL}; if (luderr) { t error( t alloc for T UDERROR fails ); exit(2); if (t rcvuderr(fd, udert) < 0) /* получить код ошибки */ t error( t uderr ); else cerr Error codeis: aderr->error endl; t free(uderr, T UDERROR); /* удалить запись с данными об ошибках */ else t error( t rcvudata ); } else cout receive msg: buf \n ; 11,4.9. Функции t sndrel, t rcvrel Прототипы функций t sndrel и t rcvrel вытпятт следующим образом: #include <tiuser.h> int t sndrel ( int fd ); int t rcvrel ( int fd ); Функция t sndrel передает запрос в используемый провайдер транспорта на разрыв соединения только в одном направлении. Процесс не может посылать сообщения в конечную точку транспортировки, обозначенную аргументом fd, но может продолжать принимать сообщения через эту точку (до получения подтверждения о приеме запроса на разрыв соединения). В случае успещного выполнения эта функция возвращает О, а в случае неудачи возвращает -1. Если точка fd задана как неблокирующая и запрос на разрыв соединения в одном направлении не может бьггь передан в используемый провайдер транспорта немедленно, функция возвращает -1 и переменной t ermo присваивается значение TFLOW. функция tjrcxrel подтверждает прием запроса на разрыв соединения. После вызова этой функции процесс не должен пьггаться принимать сообщения через конечную точку транспортировки, указанную аргументом fd. В случае успешного выполнения данная функция возврашает О, а в случае неудачи возвращает Л. Функции t sndrel и t rcvrel поддерживаются не всеми провайдерами транспорта. Если провайдер не поддерживает эти функции, а они вызываются то возвращается значение -1 и переменной t errno присваивается значение TNOTSUPPORT. В следующем примере показано, как в конечную точку транспортировки посылается запрос на разрыв соединения в одном направлении. Затем программа ждет подтверждения уведомления о разрыве соединения: if (sndrel(fd) <0) t error( sndrel ); else if (t rcvrel(fd) < 0) t error( rcvrel ); 11.4.10. Функции t snddls, t rcvdis Прототипы функций t snddis и t rcvdis: #include <tiuser.h> int t snddis ( int fd. struct t call* call ); int tjrcvdis ( int fd, struct t discon* conn ); Функция t snddis служит для аварийного разрыва установленного ранее транспортного соединения и отклонения клиентского запроса на соединение. При отклонении запроса на соединение в поле call- >sequence указывается, какой запрос отклоняется. При аварийном разрыве соединения аргумент call может иметь значение NULL; в противном случае используется только поле call->udata, в котором содержатся пользовательские данные, передаваемые в удаленную транспортную точку вместе с уведомлением об аварийном разъединении. В случае успешного выполнений эта функция возвращает О, а в случае неудачи возвращает -I. Функция t rc\dis служит для отправки уведомления об аварийном разрыве соединения и отправки вместе с уведомлением пользовательских данных. Аргумент conn может иметь значение NULL, если процесс не запрашивает о пользовательских данных и причине преждевременного расторжения. В противном случае conn содержит адрес переменной типа struct t discon. Эта структура объявляется следующим образом: struct t discon ftruct netbuf udata; reason; sequence; Поле conn->udata содержит пользовательские данные, переданные одновременно с вызовом tsnddis. Поле com->reason содержит код причины разъединения, который зависит от провайдера транспорта. Поле conn->se-quence имеет значение только для серверного процесса, выполнившего несколько вызовов tjisten, и используется для того, чтобы определить, какой клиентский процесс инициировал вызов tconnect и, затем, вызов tsnddis. В случае успешного выполнения эта функция возвращает О, а в случае неудачи возвращает -1. В следующем примере в конечную точку транспортировки посылается запрос на аварийный разрыв соединения: if (t snddis(fd) < 0) t error( t snddis ); Ниже функция t rcvdis используется для получения кода хфичины отклонения запроса на соединение: if (t connect(fd, call, call) < && t errno==TLOOK) if (t loolc(fd)==T DISCONNECT) { Struct t discon *conn = (struct t discon*)t alloc(fd, T DIS, T ALL); if (Iconn) t error( t alloc for T DIS fails ); else if (t rcvdis(fd, conn) < 0) t error( t rcvdis ); else cout Disconnect reason code: conn->reason endl: 11.4.11. Функция t close Прототип функции tclose выглядит следующим образом: #include <tiuser.h> int tjclose ( int fd ); Функция tclose заставляет провайдер транспорта освободить все системные ресурсы, которые выделены для конечной точки транспортировки, указанной аргументом fd, и закрывает файл устройства, связанный с этим провайдером. Данную функцию следует вызывать после завершения соединения с транспортной конечной точкой, осуществленного посредством вызова tsndrel или tsnddis. В случае успешного выполнения рассматриваемая функция возвращает О, а в случае неудачи возвращает -1. Вот как можно закрыть конечную точку транспортировки: if (t close(fd) < 0) t error( t close ); 11.5. Класс TLI в этом разделе описан класс ТЫ, который выполняет функции, похожие на функции класса sock (см. раздел 11.2). В частности, класс ТЫ инкапсулирует все низкоуровневые интерфейсы системных вызовов ТЫ и обеспечивает управление динамической памятью, используемой для хранения ТЫ-данных (таких как struct tcall, struct tJind и т.д.). Это позволяет сократить время обучения и программирования для тех пользователей, которые хотят с помощью интерфейса транспортного уровня решать задачи межпроцессного взаимодействия. Кроме того, класс ТЫ способствует максимальной унификации пользовательских приложений. Класс ТЫ определяется в заголовке tli.h следующим образом: #ifndef TLI H ♦define TLI H /* Определение класса тЫ */ ♦include <iostream.h> ♦include <unistd.h> ♦include <string.h> ♦include <tiuser.h> ♦include <stropts.h> * ♦include <fcntl.h> ♦include <stdio.h> ♦include <stdlib.h> tinclude <signal.h> ♦include <netdir.h> ♦include <netconfig.li> ♦define UDP TRANS /dev/ticlts ♦define TCP TRANS /dev/ticotsord ♦define DISCONNECT -1 class tli { private: int tid; int local addr; struct nd addrlist struct netconfig int rc; дескриптор транспорта /* адрес транспорта для локального IPC */ *addr; /* адрес транспорта для сетевого IPC */ *nconf; /* файл устройства провайдера транспорта */ ТЫ functions return status code /* вьщелить структуру для передачи дейтаграммного сообщения в конечную точку сети Internet */ struct t unitdata* alloc ud ( int nsid, char* service, char* host ) struct t unitdata* ud=(struct t unitdata*)t alloc( nsid==-l ? tid : nsid, (T UNITDATA), (T ALL)); if (!ud) t error( t alloc of t unitdata ); return 0; struct nd hostserv hostserv; struct netconfig *ncf; TI address struct nd addrlist *Addr; void *hp; if ((hp=setnetpath{)) == 0) { perror( Cant init network ); return 0; hostserv.h host = host; hostserv.h serv = service; while ({ncf=getnetpath(hp)) != 0) ( if (ncf->nc semantics == NC TPI CLTS S& netdir getbyname(ncf, shostserv, &Addr)==0) break; endnetpath(hp) ; if (Incf) { cerr Cant find transport for service \n ; return 0; ud->addr = *{Addr->n addrs); return ud; /* выделить структуру для передачи дейтаграммного сообщения в конечную точку */ struct t unitdata* alloc ud { int nsid, int port no ) struct t unitdata* ud={struct t unitdata*)t alloc{ nsid==-l ? tid : nsid, (T UNITDATA), {T ALL)); if {!ud) t error{ t alloc of t unitdata ); return 0; ud->addr.len = sizeof(int); *(int*)ud->addr.buf = port no; return ud; public: /* конструктор, обеспечивающий создание конечной транспортной точки для локального IPC */ tli{ int srv addr, int connless = 0 ) { localaddr = srv addr; nconf =0; addr =0; if {{tid t open(connless ? UDP TRANS : TCP TRANS, 0 RDWR, 0)) < 0) t error{ t open fails ); /* конструктор, обеспечивающий создание конечной транспортной точки для сетевого IPC */ tli{ char* hostname, char* service, int connless=0 ) struct nd hostserv hostserv; void *hp; int type = connless ? NC TPI CLTS : NC TPI COTS ORD; local addr = 0; /* найти провайдер транспорта для указанных хоста и сервиса */ if ({hp=setnetpath{)) == 0) { perror( Cant init network ); exitd) ; hostserv.h host = hostname; hostserv.h serv = service; while {{nconf=getnetpath(hp)) != 0) if (nconf->nc semantics == type && netdir getbyname{nconf, shostserv, saddr)==0) break; endnetpath{hp); if {nconf == 0 ) cerr No transport found for service: service \n ; else if {{tid=t open(nconf->nc device, 0 RDWR, 0)) < 0) t error( t open fails ); /* функция-деструктор */ ~tli() { shutdown 0; close {tid); ); /* проверить статус успешного выполнения конструктора */ int good О { return tid >= 0; ); /* позволить провайдеру транспорта г1рисвоить имя конечной точке */ . int Bind anonymous{ ) { return t bind{tid. О, 0); /* присвоить имя конечной точке */ int Bind{) struct t bind *bind;
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |