UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
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
Когда мы проверяем, соответствует ли количество возвращенной управляющей информации по меньшей мере размеру длинного целого, нужно проявить осторожность, преобразуя значение sizeof в целое число. Оператор sizeof возвращает целое число без знака, но существует вероятность того, что значение возвращенного поля len будет -1. Поскольку при выполнении операции сравнения слева располагается значение со знаком, а справа — без знака, компилятор преобразует значение со знаком в значение без знака. Если рассматривать -1 как целое без знака в архитектуре с дополнением до 2, это число получается очень большим, то есть -1 оказывается больше 4 (если предположить, что длинное целое число занимает 4 байта).
31-33
T_BIND_ACK
addr
bind_ack
34-39
T_ERROR_ACK
Чтобы увидеть ошибки, которые могут возникнуть в результате запроса на связывание, мы слегка изменим нашу функцию
main
solaris % <b>tpi_daytime 127.0.0.1</b>
T_ERROR_ACK from bind (3, 0)
В этой системе значение константы
EACCESS
solaris % <b>tpi_daytime 127.0.0.1</b>
T_ERROR_ACK from bind (23, 0)
В данной системе значение константы
EADDRBUSY
Следующая функция показана в листинге 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);
28 ctlbuf.len = 0;
29 ctlbuf.buf = (char*)&rcvbuf;
30 flags = RS_HIPRI;
31 Getmsg(fd, &ctlbuf, NULL, &flags);
32 if (ctlbuf.len < (int)sizeof(long))