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

Листинг 55.7. Клиент, использующий потоковые сокеты

sockets/is_seqnum_cl.c

#include

#include "is_seqnum.h"

int

main(int argc, char *argv[])

{

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

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

int cfd;

ssize_t numRead;

struct addrinfo hints;

struct addrinfo *result, *rp;

if (argc < 2 || strcmp(argv[1], "-help") == 0)

usageErr("%s server-host [sequence-len]\n", argv[0]);

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

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

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

hints.ai_canonname = NULL;

hints.ai_addr = NULL;

hints.ai_next = NULL;

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

hints.ai_socktype = SOCK_STREAM;

hints.ai_flags = AI_NUMERICSERV;

if (getaddrinfo(argv[1], PORT_NUM, &hints, &result)!= 0)

errExit("getaddrinfo");

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

подходящую для успешного соединения с сокетом */

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

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

if (cfd == -1)

continue; /* В случае ошибки пробуем следующий адрес */

 if (connect(cfd, rp->ai_addr, rp->ai_addrlen)!= -1)

break; /* Успех */

/* Сбой соединения: закрываем этот сокет и пробуем следующий адрес */

close(cfd);

}

if (rp == NULL)

fatal("Could not connect socket to any address");

freeaddrinfo(result);

/* Отправляем длину запрашиваемой последовательности с символом новой строки в конце */

reqLenStr = (argc > 2)? argv[2]: "1";

if (write(cfd, reqLenStr, strlen(reqLenStr))!= strlen(reqLenStr))

fatal("Partial/failed write (reqLenStr)");

if (write(cfd, "\n", 1)!= 1)

fatal("Partial/failed write (newline)");

/* Считываем и выводим число, полученное от сервера */

numRead = readLine(cfd, seqNumStr, INT_LEN);

if (numRead == -1)

errExit("readLine");

if (numRead == 0)

fatal("Unexpected EOF from server");

printf("Sequence number: %s", seqNumStr); /* Включает в себя '\n' */

exit(EXIT_SUCCESS); /* Закрывает 'cfd' */

}

sockets/is_seqnum_cl.c

55.12. Библиотека для работы с сокетами интернет-домена

Здесь мы воспользуемся функциями, представленными в разделе 55.10, чтобы реализовать библиотеку для выполнения задач, которые обычно необходимо решать при работе с сокетами интернет-домена (данная библиотека инкапсулирует многие из тех шагов, которые мы показали на примере программ в разделе 55.11). Так как эти функции используют вызовы getaddrinfo() и getnameinfo(), не зависящие от протокола, их можно применять как для IPv4, так и для IPv6.

Заголовочный файл с объявлением данных функций представлен в листинге 55.8. Многие из них имеют похожие аргументы.

• Аргумент host содержит строку с именем сетевого узла или его числовым адресом (для IPv4 это десятичные числа, разделенные точкой, а для IPv6 — шестнадцатеричная строка). Можно также передать аргументу host нулевой указатель, чтобы использовать IP-адрес, замкнутый на себя.

• Аргументу service можно передать либо имя службы, либо порт, заданный в виде десятичной строки.

• Аргумент type обозначает тип сокета: SOCK_STREAM или SOCK_DGRAM.

Листинг 55.8. Заголовочный файл для программы inet_sockets.c

sockets/inet_sockets.h

#ifndef INET_SOCKETS_H

#define INET_SOCKETS_H /* Не даем подключить заголовок больше одного раза */

#include

#include

int inetConnect(const char *host, const char *service, int type);

int inetListen(const char *service, int backlog, socklen_t *addrlen);

int inetBind(const char *service, int type, socklen_t *addrlen);

char *inetAddressStr(const struct sockaddr *addr, socklen_t addrlen,

char *addrStr, int addrStrLen);

#define IS_ADDR_STR_LEN 4096

/* Рекомендуемая длина строкового буфера, который нужно передать

в inetAddressStr(). Должна быть больше чем (NI_MAXHOST + NI_MAXSERV + 4) */

#endif

sockets/inet_sockets.h

Функция inetConnect() создает сокет типа type и подключает его к адресу, заданному с помощью аргументов host и service. Эта функция предназначена для TCP- и UDP-клиентов, которым нужно подключиться к серверному сокету.

#include "inet_sockets.h"

int inetConnect(const char *host, const char *service, int type);

Возвращает файловый дескриптор или -1 при ошибке

Файловый дескриптор нового сокета возвращается в качестве результата выполнения функции.

Функция inetListen() создает слушающий сокет (SOCK_STREAM), привязанный к универсальному IP-адресу и TCP-порту, заданному с помощью аргумента service. Она предназначена для использования в TCP-серверах.

#include "inet_sockets.h"

int inetListen(const char *service, int backlog, socklen_t *addrlen);

Возвращает файловый дескриптор или -1 при ошибке

Файловый дескриптор нового сокета возвращается в качестве результата выполнения функции.

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

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

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

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

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

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

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

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

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