UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
24-30T_BIND_REQT_BIND_ACKT_ERROR_ACKM_PCPROTOgetmsgRS_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_ACKgetmsgКогда мы проверяем, соответствует ли количество возвращенной управляющей информации по меньшей мере размеру длинного целого, нужно проявить осторожность, преобразуя значение sizeof в целое число. Оператор sizeof возвращает целое число без знака, но существует вероятность того, что значение возвращенного поля len будет -1. Поскольку при выполнении операции сравнения слева располагается значение со знаком, а справа — без знака, компилятор преобразует значение со знаком в значение без знака. Если рассматривать -1 как целое без знака в архитектуре с дополнением до 2, это число получается очень большим, то есть -1 оказывается больше 4 (если предположить, что длинное целое число занимает 4 байта).
31-33T_BIND_ACKaddrbind_ack34-39T_ERROR_ACKЧтобы увидеть ошибки, которые могут возникнуть в результате запроса на связывание, мы слегка изменим нашу функцию
mainsolaris % <b>tpi_daytime 127.0.0.1</b>T_ERROR_ACK from bind (3, 0)В этой системе значение константы
EACCESSsolaris % <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))
