UNIX: разработка сетевых приложений
Часть 156 из 399 Информация о книге
1 #include "unp.h"2 void3 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.c1 #include "unp.h"2 void3 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 } else19 err_sys("recvfrom error");20 }21 recvline[n] = 0; /* завершающий нуль */22 Fputs(recvline, stdout);23 }24 }Установка параметра сокетаЧетвертый аргумент функции8-10— это указатель на структуруsetsockopt, в которую записывается желательное значение тайм-аута.timevalПроверка тайм-аутаЕсли тайм-аут операции ввода-вывода истекает, функция (в данном случае15-17) возвращает ошибкуrecvfrom.EWOULDBLOCK14.3. Функции recv и send
Эти две функции аналогичны стандартным функциям
иread, но для них требуется дополнительный аргумент.write#include <sys/socket.h>ssize_t recv(int <i>sockfd</i>, void *<i>buff</i>, size_t <i>nbytes</i>, int <i>flags</i>);ssize_t send(int <i>sockfd</i>, const void *<i>buff</i>, size_t <i>nbytes</i>, int <i>flags</i>);<i>Обе функции возвращают: количество прочитанных или записанных байтов в случае успешного выполнения, -1 в случае ошибки</i>Первые три аргумента функций
иrecvсовпадают с тремя первыми аргументами функций read и write. Аргументsendлибо имеет нулевое значение, либо формируется в результате применения операции логического ИЛИ к константам, представленным в табл. 14.1.flagsТаблица 14.1. Аргумент flags для функций ввода-вывода
flags Описание recv send MSG_DONTROUTE He искать в таблице маршрутизации • MSG_DONTWAIT Только эта операция является неблокируемой • • MSG_OOB Отправка или получение внеполосных данных • MSG_PEEK Просмотр приходящих сообщений • MSG_WAITALL Ожидание всех данных •