UNIX: разработка сетевых приложений, стр. 178
Мы работаем с двумя буферами: буфер to содержит данные, направляющиеся из стандартного потока ввода к серверу, а буфер
frto
Рис. 16.1. Буфер, содержащий данные из стандартного потока ввода, идущие к сокету
Указатель
toiptrtooptr&to[MAXLINE]toiptrtooptrtoiptrНа рис. 16.2 показана соответствующая организация буфера
fr
Рис. 16.2. Буфер, содержащий данные из сокета, идущие к стандартному устройству вывода
Листинг 16.1. Функция str_cli: первая часть, инициализация и вызов функции
//nonblock/strclinonb.c 1 #include "unp.h" 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-15fcntlИнициализация указателей буфера
16-19selectОсновной цикл: подготовка к вызову функции select
20selectПодготовка интересующих нас дескрипторов
21-30tofrtofrВызов функции select
31selectСледующая часть нашей функции показана в листинге 16.2. Этот код содержит первые две проверки (из четырех возможных), выполняемые после завершения функции
selectЛистинг 16.2. Функция str_cli: вторая часть, чтение из стандартного потока ввода или сокета
//nonblock/strclinonb.c32 if (FD_ISSET(STDIN_FILENO, &rset)) {33 if ((n = read(STDIN_FILENO, toiptr, &to[MAXLINE] - toiptr)) < 0) {34 if (errno != EWOULDBLOCK)35 err_sys("read error on stdin");36 } else if (n == 0) {