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

Листинг 55.2. Заголовочный файл, применяемый программами i6d_ucase_sv.c и i6d_ucase_cl.c

sockets/i6d_ucase.h

#include

#include

#include

#include

#include "tlpi_hdr.h"

#define BUF_SIZE 10 /* Максимальный размер сообщений,

которыми обмениваются клиент и сервер */

#define PORT_NUM 50002 /* Номер серверного порта */

sockets/i6d_ucase.h

В листинге 55.3 показана серверная программа. Сервер использует функцию inet_ntop() для приведения адреса клиента (полученного с помощью вызова recvfrom()) в презентационный вид.

Клиентская программа, представленная в листинге 55.4, содержит два заметных нововведения по сравнению со старой версией, рассчитанной на домен UNIX (см. листинг 53.7). Во-первых, клиент интерпретирует аргумент командной строки как адрес сервера в формате IPv6 (остальные аргументы воспринимаются как отдельные датаграммы, которые нужно послать серверу). С помощью функции inet_pton() данный адрес приводится в двоичный вид. Во-вторых, клиент не привязывает свой сокет ни к какому адресу. Как отмечалось в подразделе 54.6.1, если у сокета в интернет-домене нет адреса, то ядро автоматически привязывает его к динамическому порту в текущей системе. Это можно наблюдать в следующей сессии командной строки, где сервер и клиент запускаются на одном и том же компьютере:

$ ./i6d_ucase_sv &

[1] 31047

$ ./i6d_ucase_cl::1 ciao Отправляем серверу в локальной системе

Server received 4 bytes from (::1, 32770)

Response 1: CIAO

Этот вывод говорит о том, что вызов recvfrom() сумел получить адрес клиентского сокета, в том числе номер его динамического порта, хотя клиент и не выполнял операцию bind().

Листинг 55.3. Сервер для изменения регистра на основе датаграммных сокетов и IPv6

sockets/i6d_ucase_sv.c

#include "i6d_ucase.h"

int

main(int argc, char *argv[])

{

struct sockaddr_in6 svaddr, claddr;

int sfd, j;

ssize_t numBytes;

socklen_t len;

char buf[BUF_SIZE];

char claddrStr[INET6_ADDRSTRLEN];

sfd = socket(AF_INET6, SOCK_DGRAM, 0);

if (sfd == -1)

errExit("socket");

memset(&svaddr, 0, sizeof(struct sockaddr_in6));

svaddr.sin6_family = AF_INET6;

svaddr.sin6_addr = in6addr_any; /* Универсальный адрес */

svaddr.sin6_port = htons(PORT_NUM);

if (bind(sfd, (struct sockaddr *) &svaddr,

sizeof(struct sockaddr_in6)) == -1)

errExit("bind");

/* Получаем сообщения, переводим их в верхний регистр и возвращаем клиенту */

for (;;) {

len = sizeof(struct sockaddr_in6);

numBytes = recvfrom(sfd, buf, BUF_SIZE, 0,

(struct sockaddr *) &claddr, &len);

if (numBytes == -1)

errExit("recvfrom");

if (inet_ntop(AF_INET6, &claddr.sin6_addr, claddrStr,

INET6_ADDRSTRLEN) == NULL)

printf("Couldn't convert client address to string\n");

else

printf("Server received %ld bytes from (%s, %u)\n",

(long) numBytes, claddrStr, ntohs(claddr.sin6_port));

for (j = 0; j < numBytes; j++)

buf[j] = toupper((unsigned char) buf[j]);

if (sendto(sfd, buf, numBytes, 0, (struct sockaddr *)

&claddr, len)!=

numBytes)

fatal("sendto");

}

}

sockets/i6d_ucase_sv.c

Листинг 55.4. Клиент для изменения регистра на основе датаграммных сокетов и IPv6

sockets/i6d_ucase_cl.c

#include "i6d_ucase.h"

int

main(int argc, char *argv[])

{

struct sockaddr_in6 svaddr;

int sfd, j;

size_t msgLen;

ssize_t numBytes;

char resp[BUF_SIZE];

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

usageErr("%s host-address msg…\n", argv[0]);

sfd = socket(AF_INET6, SOCK_DGRAM, 0); /* Создаем клиентский сокет */

if (sfd == -1)

errExit("socket");

memset(&svaddr, 0, sizeof(struct sockaddr_in6));

svaddr.sin6_family = AF_INET6;

svaddr.sin6_port = htons(PORT_NUM);

if (inet_pton(AF_INET6, argv[1], &svaddr.sin6_addr) <= 0)

fatal("inet_pton failed for address '%s'", argv[1]);

/* Отправляем сообщения серверу; направляем ответы в стандартный вывод */

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

msgLen = strlen(argv[j]);

if (sendto(sfd, argv[j], msgLen, 0, (struct sockaddr *) &svaddr,

sizeof(struct sockaddr_in6))!= msgLen)

fatal("sendto");

numBytes = recvfrom(sfd, resp, BUF_SIZE, 0, NULL, NULL);

if (numBytes == -1)

errExit("recvfrom");

printf("Response %d: %.*s\n", j — 1, (int) numBytes, resp);

}

exit(EXIT_SUCCESS);

}

sockets/i6d_ucase_cl.c

55.8. Система доменных имен (DNS)

В разделе 55.10 мы подробно рассмотрим функции getaddrinfo() и getnameinfo(), которые позволяют получать IP-адрес из имени сетевого узла и наоборот. Но перед этим нужно объяснить, как служба DNS хранит связи между именами узлов и IP-адресами.

До появления DNS имена сетевых узлов и IP-адреса связывались с помощью локального файла /etc/hosts, содержащего записи следующего вида:

# IP-address canonical hostname [aliases]

127.0.0.1 localhost

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

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

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

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

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

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

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

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

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