Уильям Стивенс - UNIX: разработка сетевых приложений
- Название:UNIX: разработка сетевых приложений
- Автор:
- Жанр:
- Издательство:Питер
- Год:2007
- Город:Санкт-Петербург
- ISBN:5-94723-991-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Тайм-аут для функции recvfrom (функция select)
Мы демонстрируем вторую технологию для установки тайм-аута (использование функции select
) в листинге 14.3. Здесь показана наша функция readable_timeo
, которая ждет, когда дескриптор станет готов для чтения, но не более заданного числа секунд.
Листинг 14.3. Функция readable_timeo: ожидание, когда дескриптор станет готов для чтения
//lib/readable_timео.c
1 #include "unp.h"
2 int
3 readable_timeo(int fd, int sec)
4 {
5 fd_set rset;
6 struct timeval tv;
7 FD_ZERO(&rset);
8 FD_SET(fd, &rset);
9 tv.tv_sec = sec;
10 tv.tv_usec = 0;
11 return (select(fd + 1, &rset, NULL, NULL, &tv));
12 /* > если дескриптор готов для чтения */
13 }
7-10
В наборе дескрипторов для чтения включается бит, соответствующий данному дескриптору. В структуре timeval
устанавливается время (число секунд), в течение которого вызывающий процесс готов ждать.
11-12
Функция select
ждет, когда дескриптор станет готов для чтения или истечет заданное время ожидания. Возвращаемое значение этой функции — это возвращаемое значение функции select
: -1 в случае ошибки, 0, если истекло время ожидания, и положительное значение, задающее число готовых дескрипторов, если таковые появились.
Эта функция не выполняет операции чтения — она просто ждет, когда дескриптор будет готов к чтению. Следовательно, эту функцию можно использовать с любым типом сокета — TCP или UDP.
Создание аналогичной функции, называемой writable_timeo
, тривиально. Эта функция ждет, когда дескриптор будет готов для записи.
Мы используем эту функцию в листинге 14.4, где показана еще одна версия нашей функции dg_cli
, приведенной в листинге 8.4. Эта новая версия вызывает функцию recvfrom
, только когда наша функция readable_timeo
возвращает положительное значение.
Мы не вызываем функцию recvfrom
, пока функция readable_timeo
не сообщит нам, что дескриптор готов для чтения. Тем самым мы гарантируем, что функция recvfrom
не заблокируется.
Листинг 14.4. Функция dg_cli, вызывающая функцию readable_timeo для установки тайм-аута
//advio/dgclitimeo1.c
1 #include "unp.h"
2 void
3 dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
4 {
5 int n;
6 char sendline[MAXLINE], recvline[MAXLINE + 1];
7 while (Fgets(sendline, MAXLINE, fp) != NULL) {
8 Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);
9 if (Readable_timeo(sockfd, 5) == 0) {
10 fprintf(stderr, "socket timeout\n");
11 } else {
12 n = Recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
13 recvline[n] = 0; /* завершающий нуль */
14 Fputs(recvline, stdout);
15 }
16 }
17 }
Тайм-аут для функции recvfrom (параметр сокета SO_RCVTIMEO)
В нашем последнем примере демонстрируется применение параметра сокета SO_RCVTIMEO
. Мы устанавливаем этот параметр один раз для дескриптора, задавая значение тайм-аута, и этот тайм-аут затем применяется ко всем операциям чтения этого дескриптора. Одна из замечательных особенностей этого метода состоит в том, что мы устанавливаем данный параметр только один раз, тогда как предыдущие два метода требовали выполнения некоторых действий перед каждой операцией, для которой мы хотели задать временной предел. Но этот параметр сокета применяется только к операциям чтения. Аналогичный параметр SO_SNDTIMEO
применяется только к операциям записи, и ни один параметр сокета не может использоваться для установки тайм-аута для функции connect
.
Листинг 14.5. Функция dg_cli, использующая параметр сокета SO_RCVTIMEO для установки тайм-аута
//advio/dgclitimeo2.c
1 #include "unp.h"
2 void
3 dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
4 {
5 int n;
6 char sendline[MAXLINE], recvline[MAXLINE + 1];
7 struct timeval tv;
8 tv.tv_sec = 5;
9 tv.tv_usec = 0;
10 Setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
11 while (Fgets(sendline, MAXLINE, fp) != NULL) {
12 Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);
13 n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
14 if (n < 0) {
15 if (errno == EWOULDBLOCK) {
16 fprintf(stderr, "socket timeout\n");
17 continue;
18 } else
19 err_sys("recvfrom error");
20 }
21 recvline[n] = 0; /* завершающий нуль */
22 Fputs(recvline, stdout);
23 }
24 }
8-10
Четвертый аргумент функции setsockopt
— это указатель на структуру timeval
, в которую записывается желательное значение тайм-аута.
15-17
Если тайм-аут операции ввода-вывода истекает, функция (в данном случае recvfrom
) возвращает ошибку EWOULDBLOCK
.
14.3. Функции recv и send
Эти две функции аналогичны стандартным функциям read
и write
, но для них требуется дополнительный аргумент.
#include
ssize_t recv(int sockfd , void * buff , size_t nbytes , int flags );
ssize_t send(int sockfd , const void * buff , size_t nbytes , int flags );
Обе функции возвращают: количество прочитанных или записанных байтов в случае успешного выполнения, -1 в случае ошибки
Первые три аргумента функций recv
и send
совпадают с тремя первыми аргументами функций read и write. Аргумент flags
либо имеет нулевое значение, либо формируется в результате применения операции логического ИЛИ к константам, представленным в табл. 14.1.
Таблица 14.1. Аргумент flags для функций ввода-вывода
flags | Описание | recv | send |
---|---|---|---|
MSG_DONTROUTE | He искать в таблице маршрутизации | • | |
MSG_DONTWAIT | Только эта операция является неблокируемой | • | • |
MSG_OOB | Отправка или получение внеполосных данных | • | |
MSG_PEEK | Просмотр приходящих сообщений | • | |
MSG_WAITALL | Ожидание всех данных | • |
■ MSG_DONTROUTE
. Этот флаг сообщает ядру, что получатель находится в нашей сети, и поэтому не нужно выполнять поиск в таблице маршрутизации. Дополнительную информацию об этом свойстве мы приводим при описании параметра сокета SO_DONTROUTE
(см. раздел 7.5). Это свойство можно включить для одной операции вывода с флагом MSG_DONTROUTE
или для всех операций вывода данного сокета, используя указанный параметр сокета.
■ MSG_DONTWAIT
. Этот флаг указывает, что отдельная операция ввода-вывода является неблокируемой. Таким образом, отпадает необходимость включать флаг отсутствия блокировки для сокета, выполнять операцию ввода-вывода и затем выключать флаг отсутствия блокировки. Неблокируемый ввод-вывод мы опишем в главе 15 вместе с включением и выключением флага отсутствия блокировки для всех операций ввода-вывода через сокет.
Интервал:
Закладка: