36 err_quit("bad length for T_ERROR_ACK");
37 error_ack = (struct T_error_ack*)&bind_ack.msg_hdr;
38 err_quit("T_ERROR_ACK from bind (%d, %d)",
39 error_ack->TLI_error, error_ack->UNIX_error);
40 default:
41 err_quit("unexpected message type: %d", bind_ack.msg_hdr.PRlM_type);
42 }
43 }
16-20
Заголовочный файл
определяет структуру T_bind_req
:
struct T_bind_req {
long PRIM_type; /* T_BIND_REQ */
long ADDR_length; /* длина адреса */
long ADDR_offset; /* смещение адреса */
unsigned long CONIND_number; /* сообщения о соединении */
/* далее следует адрес протокола для связывания */
};
Все запросы TPI определяются как структуры, начинающиеся с поля типа long
. Мы определяем свою собственную структуру bind_req
, начинающуюся со структуры T_bind_req
, после которой располагается буфер, содержащий локальный адрес для связывания. TPI ничего не говорит о содержимом буфера — оно определяется поставщиком. Поставщик TCP предполагает, что этот буфер содержит структуру sockaddr_in
.
Мы заполняем структуру T_bind_req
, устанавливая элемент ADDR
_length равным размеру адреса (16 байт для структуры адреса сокета Интернета), а элемент ADDR_offset
— равным байтовому сдвигу адреса (он следует непосредственно за структурой T_bind_req
). У нас нет гарантии, что это местоположение соответствующим образом выровнено для записи структуры sockaddr_in
, поэтому мы вызываем функцию memcpy
, чтобы скопировать структуру вызывающего процесса в нашу структуру bind_req
. Мы присваиваем элементу CONIND_number
нулевое значение, потому что мы находимся на стороне клиента, а не на стороне сервера.
21-23
TPI требует, чтобы только что созданная нами структура была передана поставщику как одно сообщение M_PROTO
. Следовательно, мы вызываем функцию putmsg
, задавая структуру bind_req
в качестве управляющей информации, без каких-либо данных и с флагом 0.
24-30
Ответом на наш запрос T_BIND_REQ
будет либо сообщение T_BIND_ACK
, либо сообщение T_ERROR_ACK
. Сообщения, содержащие подтверждение, отправляются как сообщения с высоким приоритетом (M_PCPROTO
), так что мы считываем их при помощи функции getmsg
с флагом RS_HIPRI
. Поскольку ответ является сообщением с высоким приоритетом, он получает преимущество перед всеми обычными сообщениями в потоке.
Эти два сообщения выглядят следующим образом:
struct T_bind_ack {
long PRIM_type; /* T_BIND_ACK */
long ADDR_length; /* длина адреса */
long ADDR_offset; /* смещение адреса */
unsigned long CONIND_number; /* индекс подключения для помещения
в очередь */
};
/* затем следует связанный адрес */
struct T_error_ack {
long PRIM_type; /* T_ERROR_ACK */
long ERROR_prim; /* примитивная ошибка ввода */
long TLI_error; /* код ошибки TLI */
long UNIX_error; /* код ошибки UNIX */
};
В начале каждого сообщения указан его тип, так что мы можем начать считывать ответ, предполагая, что это сообщение T_BIND_ACK
, а затем, прочитав его тип, обрабатывать его тем или иным способом. Мы не ждем никаких данных от поставщика, поэтому третий аргумент функции getmsg
мы задаем как пустой указатель.
Вильям Л Саймон , Вильям Саймон , Наталья Владимировна Макеева , Нора Робертс , Юрий Викторович Щербатых
Зарубежная компьютерная, околокомпьютерная литература / ОС и Сети, интернет / Короткие любовные романы / Психология / Прочая справочная литература / Образование и наука / Книги по IT / Словари и Энциклопедии