Для протоколов с предварительным установлением соединения программе-клиенту необходимо использовать функцию t_connect(3N) , отправляющую запрос на создание соединения с удаленным транспортным узлом. Функция t_connect(3N) имеет вид:
#include
int t_connect(int fd, const struct t_call* sndcall,
struct t_call *rcvcall);
Аргумент sndcall
содержит информацию, необходимую поставщику транспортных услуг для создания виртуального канала. Формат этой информации описывается структурой t_call
, имеющей следующие поля:
struct netbuf addr |
Адрес удаленного транспортного узла |
struct netbuf opt |
Требуемые опции протокола |
struct netbuf udata |
Прикладные данные, отправляемые вместе с управляющей информацией (запрос на установление соединения или подтверждение) |
int sequence |
В данном случае не имеет смысла |
Через аргумент revcall
программе возвращается информация о виртуальном канале после его создания: адрес удаленного узла, опции и прикладные данные, переданные удаленным узлом. Как уже отмечалось, ни TCP, ни UDP не позволяют передавать данные вместе с управляющей информацией. Программа может установить значение rcvcall
равным NULL
, если информация о канале ее не интересует.
Обычно возврат из функции t_connect(3N) происходит после окончательного установления соединения, когда виртуальный канал готов к передаче данных (конечно, в случае успешного завершения).
Для протоколов с предварительным установлением соединения программа-сервер вызывает функцию t_listen(3N) , блокируя свое выполнение до получения запроса на создание виртуального канала.
#include
int t_listen(int fd, struct t_call *call);
Информация, возвращаемая транспортным протоколом в аргументе call
, содержит параметры, переданные удаленным узлом с помощью соответствующего вызова t_connect(3N) : его адрес, установленные опции протокола, а также, в ряде случаев, прикладные данные, переданные вместе с запросом. Поле sequence
аргумента call
содержит уникальный идентификатор данного запроса.
Хотя t_listen(3N) , несмотря на название, напоминает функцию accept(2) , используемую для сокетов, сервер должен выполнить вызов другой функции — t_accept(3N) для того, чтобы фактически принять запрос и установить соединение. Функция t_accept(3N) имеет вид:
#include
int t_accept(int fd, int connfd, struct t_call *call);
Аргумент fd
адресует транспортный узел, принявший запрос (тот же, что и для функции t_listen(3N) ). Аргумент connfd
адресует транспортный узел, для которого будет установлено соединение с удаленным узлом. За создание нового транспортного узла отвечает сама программа (т.е. необходим явный вызов функции t_open(3N) ), при этом fd
может по-прежнему использоваться для обслуживания поступающих запросов.
Как и в случае t_listen(3N) , через аргумент call
передается информация об удаленном транспортном узле.
После возврата из функции t_accept(3N) между двумя узлами ( connfd
и удаленным узлом-клиентом) образован виртуальный канал, готовый к передаче прикладных данных.
Для обмена прикладными данными после установления соединения используются две функции: t_rcv(3N) для получения и t_snd(3N) для передачи. Они имеют следующий вид:
#include
int t_rcv(int fildes, char *buf, unsigned nbytes, int* flags);
int t_snd(int fildes, char *buf, unsigned nbytes, int flags);
Первые три аргумента соответствуют аналогичным аргументам системных вызовов read(2) и write (2) . Аргумент flags
функции t_snd(3N) может содержать следующие флаги:
T_EXPEDITED |
Указывает на отправление экстренных данных |
T_MORE |
Указывает, что данные составляют логическую запись, продолжение которой будет передано последующими вызовами t_snd(3N) . Напомним, что TCP обеспечивает неструктурированный поток и, следовательно, не поддерживает данной возможности |
Эту информацию принимающий узел получает с помощью t_rcv(3N ) также через аргумент flags
.
Для протоколов без предварительного установления соединения используются функции t_rcvdata(3N) и t_snddata(3N) для получения и передачи датаграмм соответственно. Функции имеют следующий вид:
#include
int t_rcvudata(int fildes, struct t_unitdata *unitdata,
int* flags);
int t_sndudata(int fildes, struct t_unitdata *unitdata);
Для передачи данных используется структура unitdata
, имеющая следующие поля:
struct netbuf addr |
Адрес удаленного транспортного узла |
struct netbuf opt |
Опции протокола |
struct netbuf udata |
Прикладные данные |
Созданный транспортный узел может быть закрыт с помощью функции t_close(3N) . Заметим, что при этом соединение, или виртуальный канал, с которым ассоциирован данный узел, в ряде случаев не будет закрыт. Функция t_close(3N) имеет вид:
Читать дальше