Читать книгу 📗 "Операционная система UNIX - Робачевский Андрей Михайлович"
Прежде чем передача данных будет возможна, транспортному узлу должен быть присвоен адрес. Эта фаза называется операцией связывания и мы уже сталкивались с ней при разговоре о сокетах в главе 3 и при обсуждении сетевой поддержки в BSD UNIX ранее в этой главе. В рассмотренных случаях связывание выполнял вызов bind(2). В TLI для этого служит функция t_bind(3N), имеющая вид:
#include <tiuser.h>int t_bind(int fd, const struct t_bind *req, struct t_bind *ret);Аргумент
fdreqretДва последних аргумента описываются структурой
t_bindstruct netbuf addr | Адрес |
unsigned qlen | Максимальное число запросов на установление связи, которые могут ожидать обработки. Имеет смысл только для протоколов с предварительным установлением соединения |
Рассмотрим три возможных формата аргумента
reqreq == NULL | Позволяет поставщику транспортных услуг самому выбрать подходящий адрес |
req != NULL req->addr.len == 0 | Позволяет поставщику транспортных услуг самому брать подходящий адрес, но определяет максимальное число запросов на установление связи, которые могут ожидать обработки |
req != NULL req->addr.len > 0 | Явно указывает требуемый адрес и максимальное число запросов на установление связи, которые могут ожидать обработки |
Во всех случаях фактическое значение адреса возвращается в структуре
retretДля протоколов с предварительным установлением соединения программе-клиенту необходимо использовать функцию t_connect(3N), отправляющую запрос на создание соединения с удаленным транспортным узлом. Функция t_connect(3N) имеет вид:
#include <tiuser.h>int t_connect(int fd, const struct t_call* sndcall, struct t_call *rcvcall);Аргумент
sndcallt_callstruct netbuf addr | Адрес удаленного транспортного узла |
struct netbuf opt | Требуемые опции протокола |
struct netbuf udata | Прикладные данные, отправляемые вместе с управляющей информацией (запрос на установление соединения или подтверждение) |
int sequence | В данном случае не имеет смысла |
Через аргумент
revcallrcvcallNULLОбычно возврат из функции t_connect(3N) происходит после окончательного установления соединения, когда виртуальный канал готов к передаче данных (конечно, в случае успешного завершения).
Для протоколов с предварительным установлением соединения программа-сервер вызывает функцию t_listen(3N), блокируя свое выполнение до получения запроса на создание виртуального канала.
#include <tiuser.h>int t_listen(int fd, struct t_call *call);Информация, возвращаемая транспортным протоколом в аргументе
callsequencecallХотя t_listen(3N), несмотря на название, напоминает функцию accept(2), используемую для сокетов, сервер должен выполнить вызов другой функции — t_accept(3N) для того, чтобы фактически принять запрос и установить соединение. Функция t_accept(3N) имеет вид:
#include <tiuser.h>int t_accept(int fd, int connfd, struct t_call *call);Аргумент
fdconnfdfdКак и в случае t_listen(3N), через аргумент
callПосле возврата из функции t_accept(3N) между двумя узлами (
connfdДля обмена прикладными данными после установления соединения используются две функции: t_rcv(3N) для получения и t_snd(3N) для передачи. Они имеют следующий вид:
#include <tiuser.h>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