Читаем UNIX: разработка сетевых приложений полностью

 8  for (;;) {

 9   if ((n = Readline(sockfd, line, MAXLINE)) == 0)

10    return; /* соединение закрывается удаленным концом */

11   if (sscanf(line, "%ld%ld", &arg1, &arg2) == 2)

12    snprintf(line, sizeof(line), "%ld\n", arg1 + arg2);

13   else

14    snprintf(line, sizeof(line), "input error\n");

15   n = strlen(line);

16   Writen(sockfd, line, n);

17  }

18 }

11-14 Мы вызываем функцию sscanf, чтобы преобразовать два аргумента из текстовых строк в целые числа типа long, а затем функцию snprintfдля преобразования результата в текстовую строку.

Эти клиент и сервер работают корректно вне зависимости от порядка байтов на их узлах.

<p>Пример: передача двоичных структур между клиентом и сервером</p>

Теперь мы изменим код клиента и сервера, чтобы передавать через сокет не текстовые строки, а двоичные значения. Мы увидим, что клиент и сервер работают некорректно, когда они запущены на узлах с различным порядком байтов или на узлах с разными размерами целого типа long(см. табл. 1.5).

Функции mainнаших клиента и сервера не изменяются. Мы определяем одну структуру для двух аргументов, другую структуру для результата и помещаем оба определения в наш заголовочный файл sum.h, представленный в листинге 5.12. В листинге 5.13 показана функция str_cli.

Листинг 5.12. Заголовочный файл sum.h

//tcpcliserv/sum.h

1 struct args {

2  long arg1;

3  long arg2;

4 };

5 struct result {

6  long sum;

7 };

Листинг 5.13. Функция str_cli, отправляющая два двоичных целых числа серверу

//tcpcliserv/str_cli09.c

 1 #include "unp.h"

 2 #include "sum.h"

 3 void

 4 str_cli(FILE *fp, int sockfd)

 5 {

 6  char sendline[MAXLINE];

 7  struct args args;

 8  struct result result;

 9  while (Fgets(sendline, MAXLINE, fp) != NULL) {

10   if (sscanf(sendline, "%ld%ld", &args.arg1, &args.arg2) != 2) {

11    printf("invalid input, %s", sendline);

12    continue;

13   }

14   Writen(sockfd, &args, sizeof(args));

15   if (Readn(sockfd, &result, sizeof(result)) == 0)

16    err_quit("str_cli: server terminated prematurely");

17   printf("%ld\n", result.sum);

18  }

19 }

10-14 Функция sscanfпреобразует два аргумента из текстовых строк в двоичные. Мы вызываем функцию writenдля отправки структуры серверу.

15-17 Мы вызываем функцию readnдля чтения ответа и выводим результат с помощью функции printf.

В листинге 5.14 показана наша функция str_echo.

Листинг 5.14. Функция str_echo, складывающая два двоичных целых числа

//tcpcliserv/str_echo09.c

 1 #include "unp.h"

 2 #include "sum.h"

 3 void

 4 str_echo(int sockfd)

 5 {

 6  ssize_t n;

 7  struct args args;

 8  struct result result;

 9  for (;;) {

10   if ((n = Readn(sockfd, &args, sizeof(args))) == 0)

11    return; /* соединение закрыто удаленным концом */

12   result.sum = args.arg1 + args.arg2;

13   Writen(sockfd, &result, sizeof(result));

14  }

15 }

9-14 Мы считываем аргументы при помощи вызова функции readn, вычисляем и запоминаем сумму и вызываем функцию writenдля отправки результирующей структуры обратно.

Если мы запустим клиент и сервер на двух машинах с аналогичной архитектурой, например на двух компьютерах SPARC, все будет работать нормально:

solaris % tcpcli09 12.106.32.254

11 22  мы вводим эти числа

33    а это ответ сервера

-11 -44

-55

Но если клиент и сервер работают на машинах с разными архитектурами, например, сервер в системе FreeBSD на SPARC, в которой используется обратный порядок байтов (big-endian), а клиент — в системе Linux на Intel с прямым порядком байтов (little-endian), результат будет неверным:

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

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

Основы программирования в Linux
Основы программирования в Linux

В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стан­дартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым. Для начинающих Linux-программистов

Нейл Мэтью , Ричард Стоунс , Татьяна Коротяева

ОС и Сети / Программирование / Книги по IT
1001 совет по обустройству компьютера
1001 совет по обустройству компьютера

В книге собраны и обобщены советы по решению различных проблем, которые рано или поздно возникают при эксплуатации как экономичных нетбуков, так и современных настольных моделей. Все приведенные рецепты опробованы на практике и разбиты по темам: аппаратные средства персональных компьютеров, компьютерные сети и подключение к Интернету, установка, настройка и ремонт ОС Windows, работа в Интернете, защита от вирусов. Рассмотрены не только готовые решения внезапно возникающих проблем, но и ответы на многие вопросы, которые возникают еще до покупки компьютера. Приведен необходимый минимум технических сведений, позволяющий принять осознанное решение.Компакт-диск прилагается только к печатному изданию книги.

Юрий Всеволодович Ревич

Программирование, программы, базы данных / Интернет / Компьютерное «железо» / ОС и Сети / Программное обеспечение / Книги по IT