UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
31.5. Функция ioctl
Говоря о потоках, мы снова возвращаемся к функции
ioctl
#include <stropts.h>
int ioctl(int <i>fd</i>, int <i>request</i>, ... /* void *<i>arg</i> */ );
<i>Возвращает: 0 в случае успешного выполнения, -1 в случае ошибки</i>
Единственным изменением относительно прототипа функции, приведенного в разделе 17.2, является включение заголовочного файла, необходимого для работы с потоками.
Существует примерно 30 запросов (
request
I_
streamio
31.6. TPI: интерфейс поставщика транспортных служб
На рис. 31.3 мы показали, что TPI — это интерфейс, предоставляющий доступ к транспортному уровню для расположенных выше уровней. Этот интерфейс используется в потоковой среде как сокетами, так и XTI. Из рис. 31.3 видно, что комбинация библиотеки сокетов и
sokmod
timod
TPI является интерфейсом, основанным на сообщениях (message-based). Он определяет сообщения, которыми обменивается приложение (например, XTI или библиотека сокетов) и транспортный уровень. Точнее, TPI задает формат этих сообщений и то, какое действие производит каждое из сообщений. Во многих случаях приложение посылает запрос поставщику (например, «Связать данный локальный адрес»), а поставщик посылает обратно ответ («Выполнено» или «Ошибка»). Некоторые события, происходящие асинхронно на стороне поставщика (например, прибытие запроса на соединение с сервером), инициируют отправку сигнала или сообщения вверх по потоку.
Мы можем обойти как XTI, так и сокеты, и использовать непосредственно TPI. В этом разделе мы заново перепишем код нашего простого клиента времени и даты с использованием TPI вместо сокетов (сокетная версия представлена в листинге 1.1). Если провести аналогию с языками программирования, то использование XTI или сокетов можно сравнить с программированием на языках высокого уровня, таких как С или Pascal, а непосредственно TPI — с программированием на ассемблере. Мы не являемся сторонниками непосредственного использования TPI в реальной жизни. Но понимание того, как работает TPI, и написание примера с использованием этого протокола позволит нам глубже понять, как работает библиотека сокетов в потоковой среде.
В листинге 31.1 [1] показан наш заголовочный файл
tpi_daytime.h
Листинг 31.1. Наш заголовочный файл tpi_daytime.h
//streams/tpi_daytime.h
1 #include "unpxti.h"
2 #include <sys/stream.h>
3 #include <sys/tihdr.h>
4 void tpi_bind(int, const void*, size_t);
5 void tpi_connect(int, const void*, size_t);
6 ssize_t tpi_read(int, void*, size_t);
7 void tpi_close(int);
Нам нужно включить еще один дополнительный заголовочный файл помимо
<sys/tihdr.h>
Листинг 31.2. Функция main для нашего клиента времени и даты с использованием TPI
//streams/tpi_daytime.c
1 #include "tpi_daytime.h"
2 int
3 main(int argc, char **argv)
4 {
5 int fd, n;
6 char recvline[MAXLINE + 1];
7 struct sockaddr_in myaddr, servaddr;
8 if (argc != 2)
9 err_quit("usage: tpi_daytime <Ipaddress>");
10 fd = Open(XTI_TCP, O_RDWR, 0);
11 /* связываем произвольный локальный адрес */
12 bzero(&myaddr, sizeof(myaddr));
13 myaddr.sin_family = AF_INET;
14 myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
15 myaddr.sin_port = htons(0);
16 tpi_bind(fd, &myaddr, sizeof(struct sockaddr_in));
17 /* заполняем адрес сервера */
18 bzero(&servaddr, sizeof(servaddr));
19 servaddr.sin_family = AF_INET;
20 servaddr.sin_port = htons(13); /* сервер времени и даты */
21 Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
22 tpi_connect(fd, &servaddr, sizeof(struct sockaddr_in));
23 for (;;) {
24 if ((n = tpi_read(fd, recvline, MAXLINE)) <= 0) {
25 if (n == 0)
26 break;
27 else
28 err_sys("tpi_read error");
29 }
30 recvline[n] = 0; /* завершающий нуль */
31 fputs(recvline, stdout);
32 }
33 tpi_close(fd);
34 exit(0);
35 }
10-16
/dev/tcp
INADDR_ANY
tpi_bind