Чтение онлайн

на главную

Жанры

UNIX: разработка сетевых приложений
Шрифт:

Эти два сообщения выглядят следующим образом:

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
мы задаем как пустой указатель.

ПРИМЕЧАНИЕ

Когда мы проверяем, соответствует ли количество возвращенной управляющей информации по меньшей мере размеру длинного целого, нужно проявить осторожность, преобразуя значение sizeof в целое число. Оператор sizeof возвращает целое число без знака, но существует вероятность того, что значение возвращенного поля len будет -1. Поскольку при выполнении операции сравнения слева располагается значение со знаком, а справа — без знака, компилятор преобразует значение со знаком в значение без знака. Если рассматривать -1 как целое без знака в архитектуре с дополнением до 2, это число получается очень большим, то есть -1 оказывается больше 4 (если предположить, что длинное целое число занимает 4 байта).

Обработка ответа

31-33
Если ответ — это сообщение
T_BIND_ACK
, то связывание прошло успешно, и мы возвращаемся. Фактический адрес, связанный с точкой доступа, возвращается в элементе
addr
нашей структуры
bind_ack
, которую мы игнорируем.

34-39
Если ответ — это сообщение
T_ERROR_ACK
, мы проверяем, было ли сообщение получено целиком, и выводим три значения, содержащиеся в возвращенной структуре. В этой простой программе при возникновении ошибки мы просто прекращаем выполнение и ничего не возвращаем вызывающему процессу.

Чтобы увидеть ошибки, которые могут возникнуть в результате запроса на связывание, мы слегка изменим нашу функцию

main
и попробуем связать какой- либо порт, отличный от 0. Например, если мы попробуем связать порт 1 (что требует прав привилегированного пользователя, так как это порт с номером меньше 1024), мы получим следующий результат:

solaris % tpi_daytime 127.0.0.1

T_ERROR_ACK from bind (3, 0)

В этой системе значение константы

EACCESS
равно 3. Если мы поменяем номер порта, задав значение большее 1023, но используемое в настоящий момент другой точкой доступа TCP, мы получим:

solaris % tpi_daytime 127.0.0.1

T_ERROR_ACK from bind (23, 0)

В данной системе значение константы

EADDRBUSY
равно 23.

Следующая функция показана в листинге 31.4. Это функция

tpi_connect
, устанавливающая соединение с сервером.

Листинг 31.4. Функция tpi_connect: установление соединения с сервером

//streams/tpi_connect.c

1 #include "tpi_daytime.h"

2 void

3 tpi_connect(int fd, const void *addr, size_t addrlen)

4 {

5 struct {

6 struct T_conn_req msg_hdr;

7 char addr[128];

8 } conn_req;

9 struct {

10 struct l_conn_con msg_hdr;

11 char addr[128];

12 } conn_con;

13 struct strbuf ctlbuf;

14 union T_primitives rcvbuf;

15 struct T_error_ack *error_ack;

16 struct T_discon_ind *discon_ind;

17 int flags;

18 conn_req.msg_hdr.PRIM_type = T_CONN_REQ;

19 conn_req.msg_hdr.DEST_length = addrlen;

20 conn_req.msg_hdr.DEST_offset = sizeof(struct T_conn_req);

21 conn_req.msg_hdr.OPT_length = 0;

22 conn_req.msg_hdr.OPT_offset = 0;

23 memcpy(conn_req.addr, addr, addrlen); /* sockaddr_in{} */

24 ctlbuf.len = sizeof(struct T_conn_req) + addrlen;

25 ctlbuf.buf = (char*)&conn_req;

26 Putmsg(fd, &ctlbuf, NULL, 0);

27 ctlbuf.maxlen = sizeof(union T_primitives);

Поделиться:
Популярные книги

Месть бывшему. Замуж за босса

Россиус Анна
3. Власть. Страсть. Любовь
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Месть бывшему. Замуж за босса

Корсар

Русич Антон
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
6.29
рейтинг книги
Корсар

Последний попаданец

Зубов Константин
1. Последний попаданец
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Последний попаданец

Уязвимость

Рам Янка
Любовные романы:
современные любовные романы
7.44
рейтинг книги
Уязвимость

Последняя Арена 4

Греков Сергей
4. Последняя Арена
Фантастика:
рпг
постапокалипсис
5.00
рейтинг книги
Последняя Арена 4

Прометей: владыка моря

Рави Ивар
5. Прометей
Фантастика:
фэнтези
5.97
рейтинг книги
Прометей: владыка моря

Ваше Сиятельство 8

Моури Эрли
8. Ваше Сиятельство
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Ваше Сиятельство 8

Титан империи 4

Артемов Александр Александрович
4. Титан Империи
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Титан империи 4

Прометей: каменный век II

Рави Ивар
2. Прометей
Фантастика:
альтернативная история
7.40
рейтинг книги
Прометей: каменный век II

Наизнанку

Юнина Наталья
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Наизнанку

Вечная Война. Книга VIII

Винокуров Юрий
8. Вечная Война
Фантастика:
боевая фантастика
юмористическая фантастика
космическая фантастика
7.09
рейтинг книги
Вечная Война. Книга VIII

Генерал-адмирал. Тетралогия

Злотников Роман Валерьевич
Генерал-адмирал
Фантастика:
альтернативная история
8.71
рейтинг книги
Генерал-адмирал. Тетралогия

Идеальный мир для Лекаря 6

Сапфир Олег
6. Лекарь
Фантастика:
фэнтези
юмористическая фантастика
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 6

Сумеречный Стрелок 5

Карелин Сергей Витальевич
5. Сумеречный стрелок
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Сумеречный Стрелок 5