Читать книгу 📗 "Основы программирования в Linux - Мэтью Нейл"
char from server = Вserving client on fd 6server waitingremoving client on fd 5server waitingchar from server = Вremoving client on fd 6server waiting[2] Done ./client3[3]- Done ./client3[4]+ Done ./client3Для полноты аналогии, упомянутой в начале главы, в табл. 15.5 приведены параллели между соединениями на базе сокетов и телефонными переговорами.
Таблица 15.5
| Телефон | Сетевые сокеты |
|---|---|
| Звонок в компанию по номеру 555-0828 | Подключение к IP-адресу 127.0.0.1 |
| Ответ на звонок секретаря приемной | Установка соединения с remote host |
| Просьба соединить с финансовым отделом. | Маршрутизация с помощью заданного порта (9734) |
| Ответ на звонок администратора финансового отдела | Вызов select |
| Звонок переадресован свободному менеджеру по работе с корпоративными заказчиками | Сервер вызывает accept |
Дейтаграммы
В этой главе мы сосредоточились на программировании приложений, поддерживающих связь со своими клиентами с помощью TCP-соединений на базе сокетов. Существуют ситуации, в которых затраты на установку и поддержку соединения с помощью сокетов излишни.
Хорошим примером может служить сервис
daytimeСервис
daytimeСервисы, предоставляемые по UDP-протоколу, применяются в тех случаях, когда клиенту нужно создать короткий запрос к серверу, и он ожидает единственный короткий ответ. Если стоимость времени процессора достаточно низкая, сервер способен обеспечить такой сервис, обрабатывая запросы клиентов по одному и разрешая операционной системе хранить очередь входящих запросов. Такой подход упрощает программирование сервера.
Поскольку UDP — не дающий гарантий сервис, вы можете столкнуться с потерей вашей дейтаграммы или ответа сервера. Если данные важны для вас, возможно, придется тщательно программировать ваших UDP-клиентов, проверяя ошибки и при необходимости повторяя попытки. На практике в локальных сетях UDP-дейтаграммы очень надежны.
Для доступа к сервису, обеспечиваемому UDP-протоколом, вам следует применять системные вызовы
socketclosereadwritesendtorecvfromДалее приведена модифицированная версия программы getdate.c, которая получает дату с помощью сервиса UDP-дейтаграмм. Изменения по сравнению с предыдущей версией выделены цветом.
/* Начните с обычных include и объявлений. */#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <stdio.h>#include <unistd.h>#include <stdlib.h>int main(int argc, char *argv[]) { char *host; int sockfd; int len, result; struct sockaddr_in address; struct hostent *hostinfo; struct servent *servinfo; char buffer[128]; if (argc == 1) host = "localhost"; else host = argv[1]; /* Ищет адрес хоста и сообщает об ошибке, если не находит. */ hostinfo = gethostbyname(host); if (!hostinfo) { fprintf(stderr, "no host: %sn", host); exit(1); } /* Проверяет наличие на компьютере сервиса daytime. */<i> servinfo = getservbyname("daytime", "udp");</i> if (!servinfo) { fprintf(stderr, "no daytime servicen"); exit(1); } printf("daytime port is %dn", ntohs(servinfo->s_port));<i> /* Создает UDP-сокет. */</i><i> sockfd = socket(AF_INEТ, SOCK_DGRAM, 0); </i><i> /* Формирует адрес для использования в вызовах sendto/recvfrom... */</i> address.sin_family = AF_INET; address.sin_port = servinfo->s_port; address.sin_addr = *(struct in_addr*)*hostinfo->h_addr_list; len = sizeof(address);<i> result = sendto(sockfd, buffer, 1, 0, (struct sockaddr *)&address, len);</i><i> result = recvfrom(sockfd, buffer, sizeof(buffer), 0,</i><i> (struct sockaddr *)&address, &len);</i> buffer [result] = ' '; printf("read %d bytes: %s", result, buffer); close(sockfd);