Читать книгу 📗 "Операционная система UNIX - Робачевский Андрей Михайлович"
T_EXPEDITED | Указывает на отправление экстренных данных |
T_MORE | Указывает, что данные составляют логическую запись, продолжение которой будет передано последующими вызовами t_snd(3N). Напомним, что TCP обеспечивает неструктурированный поток и, следовательно, не поддерживает данной возможности |
Эту информацию принимающий узел получает с помощью t_rcv(3N) также через аргумент
flagsДля протоколов без предварительного установления соединения используются функции t_rcvdata(3N) и t_snddata(3N) для получения и передачи датаграмм соответственно. Функции имеют следующий вид:
#include <tiuser.h>int t_rcvudata(int fildes, struct t_unitdata *unitdata, int* flags);int t_sndudata(int fildes, struct t_unitdata *unitdata);Для передачи данных используется структура
unitdatastruct netbuf addr | Адрес удаленного транспортного узла |
struct netbuf opt | Опции протокола |
struct netbuf udata | Прикладные данные |
Созданный транспортный узел может быть закрыт с помощью функции t_close(3N). Заметим, что при этом соединение, или виртуальный канал, с которым ассоциирован данный узел, в ряде случаев не будет закрыт. Функция t_close(3N) имеет вид:
#include <tiuser.h>int t_close(int fd);где
fdЗавершая разговор о программном интерфейсе TLI, необходимо упомянуть об обработке ошибок. Для большинства функций TLI свидетельством ошибки является получение -1 в качестве возвращаемого значения. Напротив, в случае нормального завершения эти функции возвращают 0. Как правило, при неудачном завершении функции TLI код ошибки сохраняется в переменной
t_errnoerrno#include <tiuser.h>void t_error(const char *errmsg);При вызове t_error(3N) после неудачного завершения какой-либо функции TLI будет выведено сообщение
errmsgt_errnot_errnoTSYSERRerrnoВ заключение в качестве иллюстрации программного интерфейса TLI приведем пример приложения клиент-сервер. Как и в предыдущих примерах, сервер принимает сообщения от клиента и отправляет их обратно. Клиент, в свою очередь, выводит полученное сообщение на экран. В качестве сообщения, как и прежде, выступает жизнерадостное приветствие "Здравствуй, мир!".
#include <sys/types.h>#include <sys/socket.h>#include <tiuser.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdio.h>#include <fcntl.h>#include <netdb.h>/* Номер порта, известный клиентам */#define PORTNUM 1500main(argc, argv)int argc;char *argv[];{ /* Дескрипторы транспортных узлов сервера */ int tn, ntn; int pid, flags; int nport; /* Адреса транспортных узлов сервера и клиента */ struct sockaddr_in serv_addr, *clnt_addr; struct hostent *hp; char buf[80], hname[80]; struct t_bind req; struct t_call *call; /* Создадим транспортный узел. В качестве поставщика транспортных услуг выберем модуль TCP */ if ((tn = t_open("/dev/tcp", O_RDWR, NULL)) == -1) { t_error("Ошибка вызова t_open()"); exit(1); } /* Зададим адрес транспортного узла — он должен быть известен клиенту */ nport = PORTNUM; /* Приведем в соответствие порядок следования байтов для хоста и сети */ nport = htons((u_short)nport); bzero(&serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = nport;