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

на главную - закладки

Жанры

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

17-22
Мы заполняем другую структуру адреса сокета Интернета, внося в нее IP-адрес сервера (из командной строки) и порт (13). Мы вызываем нашу функцию
tpi_connect
для установления соединения.

Считывание данных с сервера, копирование в стандартный поток вывода

23-33
Как и в случае других клиентов времени и даты, мы просто копируем данные, пришедшие по соединению, в стандартный поток вывода, останавливаясь при получении признака конца файла, присланного сервером (например, сегмент FIN).
Мы сделали этот цикл похожим на тот, который использовался в коде сокетного клиента (см. листинг 1.1), поскольку наша функция
tpi_read
при нормальном завершении соединения на стороне сервера будет возвращать нулевое значение. Затем мы вызываем нашу функцию
tpi_close
для того, чтобы закрыть эту точку доступа.

Наша функция

tpi_bind
показана в листинге 31.3.

Листинг 31.3. Функция tpi_bind: связывание локального адреса с точкой доступа

//streams/tpi_bind.c

1 #include "tpi_daytime.h"

2 void

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

4 {

5 struct {

6 struct T_bind_req msg_hdr;

7 char addr[128];

8 } bind_req;

9 struct {

10 struct T_bind_ack msg_hdr;

11 char addr[128];

12 } bind_ack;

13 struct strbuf ctlbuf;

14 struct T_error_ack *error_ack;

15 int flags;

16 bind_req.msg_hdr.PRIM_type = T_BIND_REQ;

17 bind_req.msg_hdr.ADDR_length = addrlen;

18 bind_req.msg_hdr.ADDR_offset = sizeof(struct T_bind_req);

19 bind_req.msg_hdr.CONIND_number = 0;

20 memcpy(bind_req.addr, addr, addrlen); /* sockaddr_in{} */

21 ctlbuf.len = sizeof(struct T_bind_req) + addrlen;

22 ctlbuf.buf = (char*)&bind_req;

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

24 ctlbuf.maxlen = sizeof(bind_ack);

25 ctlbuf.len = 0;

26 ctlbuf.buf = (char*)&bind_ack;

27 flags = RS_HIPRI;

28 Getmsg(fd, &ctlbuf, NULL, &flags);

29 if (ctlbuf.len < (int)sizeof(long))

30 err_quit("bad length from getmsg");

31 switch (bind_ack.msg_hdr.PRIM_type) {

32 case T_BIND_ACK:

33 return;

34 case T_ERROR_ACK:

35 if (ctlbuf.len < (int)sizeof(struct T_error_ack))

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 }

Заполнение
структуры T_bind_req

16-20
Заголовочный файл
<sys/tihdr.h>
определяет структуру
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
нулевое значение, потому что мы находимся на стороне клиента, а не на стороне сервера.

Вызов функции putmsg

21-23
TPI требует, чтобы только что созданная нами структура была передана поставщику как одно сообщение
M_PROTO
. Следовательно, мы вызываем функцию
putmsg
, задавая структуру
bind_req
в качестве управляющей информации, без каких-либо данных и с флагом 0.

Вызов функции getmsg для чтения сообщений с высоким приоритетом

24-30
Ответом на наш запрос
T_BIND_REQ
будет либо сообщение
T_BIND_ACK
, либо сообщение
T_ERROR_ACK
. Сообщения, содержащие подтверждение, отправляются как сообщения с высоким приоритетом (
M_PCPROTO
), так что мы считываем их при помощи функции
getmsg
с флагом
RS_HIPRI
. Поскольку ответ является сообщением с высоким приоритетом, он получает преимущество перед всеми обычными сообщениями в потоке.

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

Стеллар. Трибут

Прокофьев Роман Юрьевич
2. Стеллар
Фантастика:
боевая фантастика
рпг
8.75
рейтинг книги
Стеллар. Трибут

Его огонь горит для меня. Том 2

Муратова Ульяна
2. Мир Карастели
Фантастика:
юмористическая фантастика
5.40
рейтинг книги
Его огонь горит для меня. Том 2

На границе империй. Том 9. Часть 4

INDIGO
17. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 4

Наследник

Кулаков Алексей Иванович
1. Рюрикова кровь
Фантастика:
научная фантастика
попаданцы
альтернативная история
8.69
рейтинг книги
Наследник

Совершенно несекретно

Иванов Дмитрий
15. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Совершенно несекретно

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

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

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

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

Единственная для темного эльфа 3

Мазарин Ан
3. Мир Верея. Драконья невеста
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Единственная для темного эльфа 3

Жандарм

Семин Никита
1. Жандарм
Фантастика:
попаданцы
альтернативная история
аниме
4.11
рейтинг книги
Жандарм

Долгий путь домой

Русич Антон
Вселенная EVE Online
Фантастика:
космическая фантастика
попаданцы
6.20
рейтинг книги
Долгий путь домой

Прогрессор поневоле

Распопов Дмитрий Викторович
2. Фараон
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Прогрессор поневоле

Наследие Маозари 6

Панежин Евгений
6. Наследие Маозари
Фантастика:
попаданцы
постапокалипсис
рпг
фэнтези
эпическая фантастика
5.00
рейтинг книги
Наследие Маозари 6

Я еще не барон

Дрейк Сириус
1. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я еще не барон

Лолита

Набоков Владимир Владимирович
Проза:
классическая проза
современная проза
8.05
рейтинг книги
Лолита