Читаем Linux API. Исчерпывающее руководство полностью

/* Формируем адрес сервера на основе первого аргумента командной строки */

sfd = inetConnect(argv[1], SERVICE, SOCK_DGRAM);

if (sfd == -1)

fatal("Could not connect to server socket");

/* Посылаем серверу остальные аргументы в виде отдельных датаграмм */

for (j = 2; j < argc; j++) {

len = strlen(argv[j]);

if (write(sfd, argv[j], len)!= len)

fatal("partial/failed write");

numRead = read(sfd, buf, BUF_SIZE);

if (numRead == -1)

errExit("read");

printf("[%ld bytes] %.*s\n", (long) numRead, (int) numRead, buf);

}

exit(EXIT_SUCCESS);

}

sockets/id_echo_cl.c

Ниже показан пример того, что мы увидим при запуске сервера и двух экземпляров клиента:

$ su Для привязки к зарезервированному

порту нужны привилегии

Password:

# ./id_echo_sv Сервер переходит в фоновый режим

# exit Отказываемся от прав администратора

$ ./id_echo_cl localhost hello world Этот клиент отправляет две датаграммы

[5 bytes] hello Клиент выводит ответ, полученный от сервера

[5 bytes] world

$ ./id_echo_cl localhost goodbye Этот клиент шлет одну датаграмму

[7 bytes] goodbye

56.3. Параллельный TCP-сервер echo

TCP-служба echo тоже работает на порте под номером 7. Сервер принимает соединение и входит в бесконечный цикл, считывая все переданные ему данные и отправляя их обратно клиенту с помощью того же сокета. Сервер продолжает выполнять чтение, пока не обнаружит конец файла; после этого он закрывает свой сокет (чтобы клиент тоже получил символ конца файла, если все еще продолжает читать данные из своего сокета).

Клиент может отправить серверу данные неограниченного объема (следовательно, обслуживание клиента может занять неопределенное время), так что в подобном случае подходит архитектура параллельного сервера, которая позволяет работать с несколькими клиентами одновременно. Реализация серверного приложения показана в листинге 56.4 (реализация клиента для этой службы будет представлена в разделе 57.2). Стоит отметить следующие моменты.

• Чтобы стать демоном, сервер использует функцию becomeDaemon() из раздела 37.2.

• С целью сделать программу более компактной мы применяем библиотеку для работы с сокетами интернет-домена, разработанную в листинге 55.9.

• Поскольку сервер создает потомков для каждого клиентского соединения, мы должны следить за уничтожением зомби-процессов. Для этого используется обработчик SIGCHLD.

• В основе кода сервера лежит цикл for, который принимает клиентские соединения и выполняет вызов fork() в целях создать новый дочерний процесс, обслуживающий клиента с помощью функции handleRequest(). Тем временем родитель продолжает работу цикла for, чтобы принять следующее клиентское соединение.

В реальном приложении мы бы, вероятно, предусмотрели ограничение максимального количества дочерних процессов, которые может создать наш сервер; это помогло бы защититься от удаленной атаки, заключающейся в слишком интенсивном использовании службы и создании количества потомков, приводящего к зависанию системы. Данное ограничение можно ввести путем подсчета имеющихся дочерних процессов (счетчик инкрементируется после каждого успешного вызова fork() и декрементируется при уничтожении потомка с помощью обработчика SIGCHLD). В случае достижения ограничения мы могли бы временно приостановить прием соединений (или, как вариант, принимать соединения и тут же их закрывать).

• После каждого вызова fork() в дочернем процессе дублируется файловый дескриптор для слушающего и подключающегося сокетов (см. подраздел 24.2.1). То есть взаимодействовать с клиентским сокетом может как родитель, так и потомок. Однако заниматься этим нужно только потомку, так что сразу же после выполнения fork() родитель закрывает свой дескриптор подключенного сокета. (Если не совершить данное действие, то сокет так и будет оставаться открытым; кроме того, рано или поздно родитель исчерпает допустимое количество открытых файловых дескрипторов.) Так как потомок не принимает новые соединения, он закрывает свою копию файлового дескриптора для слушающего сокета.

• Обслужив клиента, дочерний процесс завершает работу.

Листинг 56.4. Параллельный сервер, реализующий TCP-службу echo

sockets/is_echo_sv.c

#include

#include

#include

#include "become_daemon.h"

#include "inet_sockets.h" /* Объявление функций сокета вида inet*() */

#include "tlpi_hdr.h"

#define SERVICE "echo" /* Имя TCP-службы */

#define BUF_SIZE 4096

static void /* Обработчик SIGCHLD, уничтожающий дочерние процессы */

grimReaper(int sig)

{

int savedErrno; /* Сохраняем значение 'errno' на случай,

если оно здесь изменится */

savedErrno = errno;

while (waitpid(-1, NULL, WNOHANG) > 0)

continue;

errno = savedErrno;

}

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных