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

Целые числа могут иметь разное представление на серверном и клиентском компьютерах, поэтому мы переводим их в строки с символом новой строки в конце, а для их чтения применяем функцию readLine() (см. листинг 55.1).

Общий заголовочный файл

И сервер, и клиент задействуют заголовочный файл, представленный в листинге 55.5, который, в свою очередь, подключает другие файлы и определяет номер TCP-порта для нашего приложения.

Серверная программа

Серверная программа, представленная в листинге 55.6, выполняет следующие шаги.

• Начинает последовательность либо с 1, либо с числа, переданного в виде аргумента командной строки .

• Игнорирует сигнал SIGPIPE , возникающий, когда сервер пытается выполнить запись в сокет, другой конец которого был закрыт; вместо этого операция write() завершается ошибкой EPIPE.

• Вызывает функцию getaddrinfo() для получения списка структур с адресами сокетов, подключенных к TCP-порту PORT_NUM (вместо того чтобы задавать фиксированный номер порта, обычно лучше использовать имя службы). Мы указываем флаг AI_PASSIVE для привязки итогового сокета к универсальному адресу (см. раздел 54.5). Как следствие, сервер сможет принимать запросы на соединение, направленные на любой из его адресов (если их у него несколько).

• Входит в цикл, перебирающий структуры с адресами сокетов, полученными в предыдущем шаге . Цикл завершается, когда программа находит адрес, с помощью которого можно успешно создать и привязать сокет .

• Устанавливает параметр SO_REUSEADDR для сокета, созданного в предыдущем шаге . Мы вернемся к обсуждению этого параметра в разделе 57.10, где будет отмечено, что TCP-сервер обычно должен устанавливать SO_REUSEADDR для своего слушающего сокета.

• Делает сокет слушающим .

• Входит в бесконечный цикл for , который обслуживает клиентов итерационным способом (см. главу 56). Сервер не принимает очередной клиентский запрос, пока не закончит обслуживание текущего. Для каждого клиента сервер выполняет следующие шаги.

• Принимает новое соединение . Передает второму и третьему аргументу вызова accept() ненулевые указатели, чтобы получить адрес клиента (IP-адрес плюс номер порта) и направить его в стандартный вывод .

• Считывает клиентское сообщение , которое заканчивается символом новой строки, и определяет, сколько последовательных номеров запрашивает клиент. Сервер переводит эту строку в целое число и сохраняет результат в переменной reqLen .

• Возвращает клиенту текущий элемент последовательности (seqNum) в виде строки с нулевым символом в конце . Клиент может считать, что для него была выделена последовательность номеров в диапазоне от seqNum до (seqNum + reqLen — 1).

• Обновляет текущий элемент последовательности, добавляя к seqNum значение reqLen .

Листинг 55.5. Заголовочный файл, используемый программами is_seqnum_sv.c и is_seqnum_cl.c

sockets/is_seqnum.h

#include

#include

#include

#include "read_line.h" /* Объявление readLine() */

#include "tlpi_hdr.h"

#define PORT_NUM "50000" /* Номер порта для сервера */

#define INT_LEN 30 /* Размер строки, достаточный для хранения наибольшего

целого числа (включая завершающий символ '\n') */

sockets/is_seqnum.h

Листинг 55.6. Итерационный сервер, который взаимодействует с клиентами с помощью потокового сокета

sockets/is_seqnum_sv.c

#define _BSD_SOURCE /* Получаем определения NI_MAXHOST и NI_MAXSERV

из файла */

#include

#include "is_seqnum.h"

#define BACKLOG 50

int

main(int argc, char *argv[])

{

uint32_t seqNum;

char reqLenStr[INT_LEN]; /* Длина запрашиваемой последовательности */

char seqNumStr[INT_LEN]; /* Начало выделенной последовательности */

struct sockaddr_storage claddr;

int lfd, cfd, optval, reqLen;

socklen_t addrlen;

struct addrinfo hints;

struct addrinfo *result, *rp;

#define ADDRSTRLEN (NI_MAXHOST + NI_MAXSERV + 10)

char addrStr[ADDRSTRLEN];

char host[NI_MAXHOST];

char service[NI_MAXSERV];

if (argc > 1 && strcmp(argv[1], "-help") == 0)

usageErr("%s [init-seq-num]\n", argv[0]);

seqNum = (argc > 1)? getInt(argv[1], 0, "init-seq-num"): 0;

if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)

errExit("signal");

/* Вызываем getaddrinfo(), чтобы получить список адресов,

к которым можем попытаться привязать наш сокет */

memset(&hints, 0, sizeof(struct addrinfo));

hints.ai_canonname = NULL;

hints.ai_addr = NULL;

hints.ai_next = NULL;

hints.ai_socktype = SOCK_STREAM;

hints.ai_family = AF_UNSPEC; /* Поддержка IPv4 или IPv6 */

hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;

/* Универсальный IP-адрес; имя службы имеет числовой формат */

if (getaddrinfo(NULL, PORT_NUM, &hints, &result)!= 0)

errExit("getaddrinfo");

/* Перебираем полученный список, пока не находим структуру с адресом,

подходящую для создания и привязывания сокета */

optval = 1;

for (rp = result; rp!= NULL; rp = rp->ai_next) {

lfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);

if (lfd == -1)

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

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

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

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

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

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

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

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

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