Шрифт:
Рис. 16.1. Буфер, содержащий данные из стандартного потока ввода, идущие к сокету
Указатель
toiptr
указывает на следующий байт, в который данные могут быть считаны из стандартного потока ввода. Указатель tooptr
указывает на следующий байт, который должен быть записан в сокет. Число байтов, которое может быть считано из стандартного потока ввода, равно &to[MAXLINE]
минус toiptr
. Как только значение tooptr
достигает toiptr
, оба указателя переустанавливаются на начало буфера. На рис. 16.2 показана соответствующая организация буфера
fr
. В листинге 16.1 [1] представлена первая часть функции. Рис. 16.2. Буфер, содержащий данные из сокета, идущие к стандартному устройству вывода
Листинг 16.1. Функция str_cli: первая часть, инициализация и вызов функции
//nonblock/strclinonb.c
1 #include "unp.h"
1
Все исходные коды программ, опубликованные в этой книге, вы можете найти по адресу http://www.piter.com.
2 void
3 str_cli(FILE *fp, int sockfd)
4 {
5 int maxfdp1, val, stdineof;
6 ssize_t n, nwritten;
7 fd_set rset, wset;
8 char to[MAXLINE], fr[MAXLINE];
9 char *toiptr, *tooptr, *friptr, *froptr;
10 val = Fcntl(sockfd, F_GETFL, 0);
11 Fcntl(sockfd, F_SETFL, val | O_NONBLOCK);
12 val = Fcntl(STDIN_FILENO, F_SETFL, 0);
13 Fcntl(STDIN_FILENO, F_SETFL, val | O_NONBLOCK);
14 val = Fcntl(STDOUT_FILENO, F_SETFL, 0);
15 Fcntl(STDOUT_FILENO, F_SETFL, val | O_NONBLOCK);
16 toiptr = tooptr = to; /* инициализация указателей буфера */
17 friptr = froptr = fr;
18 stdineof = 0;
19 maxfdp1 = max(max(STDIN_FILENO, STDOUT_FILENO), sockfd) + 1;
20 for (;;) {
21 FD_ZERO(&rset);
22 FD_ZERO(&wset);
23 if (stdineof == 0 && toiptr < &to[MAXLINE])
24 FD_SET(STDIN_FILENO, &rset); /* чтение из стандартного потока
ввода */
25 if (friptr < &fr[MAXLINE])
26 FD_SET(sockfd, &rset); /* чтение из сокета */
27 if (tooptr != toiptr)
28 FD_SET(sockfd, &wset); /* данные для записи в сокет */
29 if (froptr != friptr)
30 FD_SET(STDOUT_FILENO, &wset); /* данные для записи в стандартный
поток вывода */
31 Select(maxfdp1, &rset, &wset, NULL, NULL);
Установка неблокируемых дескрипторов
10-15
Все три дескриптора делаются неблокируемыми при помощи функции fcntl
: сокет в направлении к серверу и от сервера, стандартный поток ввода и стандартный поток вывода. Инициализация указателей буфера
16-19
Инициализируются указатели в двух буферах и вычисляется максимальный дескриптор. Это значение, увеличенное на единицу, будет использоваться в качестве первого аргумента функции select
.