Глава 5

Глава 5

5.1. Длительность состояния TIME_WAIT должна находиться в интервале между 1 и 4 минутами, что дает величину MSL от 30 с до 2 мин.

5.2. Наши клиент-серверные программы не работают с двоичными файлами. Допустим, что первые 3 байта в файле являются двоичной единицей (1), двоичным нулем (0) и символом новой строки. При вызове функции fgets в листинге 5.4 либо считывается MAXLINE - 1 символов, либо считываются символы до символа новой строки или до конца файла. В данном примере функция считает три символа, а затем прервет строку нулевым байтом. Но вызов функции strlen в листинге 5.4 возвращает значение 1, так как она остановится на первом нулевом байте. Один байт посылается серверу, но сервер блокируется в своем вызове функции readline, ожидая символа новой строки. Клиент блокируется, ожидая ответа от сервера. Такое состояние называется зависанием, или взаимной блокировкой: оба процесса блокированы и при этом каждый ждет от другого некоторого действия, которое никогда не произойдет. Проблема заключается в том, что функция fgets обозначает нулевым байтом конец возвращаемых ею данных, поэтому данные, которые она считывает, не должны содержать нулевой байт.

5.3. Программа Telnet преобразует входные строки в NVT ASCII (см. раздел 26.4 книги [111]), что означает прерывание каждой строки 2-символьной последовательностью CR (carriage return — возврат каретки) и LF (linefeed — новая строка). Наш клиент добавляет только разделитель строк (newline), который в действительности является символом новой строки (linefeed, LF). Тем не менее можно использовать клиент Telnet для связи с нашим сервером, поскольку наш сервер отражает каждый символ, включая CR, предшествующий каждому разделителю строк.

5.4. Нет, последние два сегмента из последовательности завершения соединения не посылаются. Когда клиент посылает серверу данные после уничтожения дочернего процесса сервера (ввод строки another line, см. раздел 5.12), сервер TCP отвечает сегментом RST. Сегмент RST прекращает соединение, а также предотвращает переход в состояние TIME_WAIT на стороне сервера (конец соединения, осуществивший активное закрытие).

5.5. Ничего не меняется, потому что процесс, запущенный на узле сервера, создает прослушиваемый сокет и ждет прибытия запросов на соединение. На третьем шаге мы посылаем сегмент данных, предназначенный для установленного соединения TCP (состояние ESTABLISHED). Наш сервер с прослушиваемым сокетом не увидит этот сегмент данных, и TCP сервера по-прежнему будет посылать клиенту сегмент RST.

5.6. В листинге Д.1[1] приведена программа. Запуск этой программы в Soalris генерирует следующий вывод:

solaris % tsigpipe 192.168.1.10

SIGPIPE received

write error: Broken pipe

Начальный вызов функции sleep и переход в режим ожидания на 2 с нужен, чтобы сервер времени и даты отправил ответ и закрыл свой конец соединения. Первая функция write отправляет сегмент данных серверу, который отвечает сегментом RST (поскольку сервер времени и даты полностью закрыл свой сокет). Обратите внимание, что наш TCP позволяет писать в сокет, получивший сегмент FIN. Второй вызов функции sleep позволяет получить от сервера сегмент RST, а во втором вызове функции write генерируется сигнал SIGPIPE. Поскольку наш обработчик сигналов возвращает управление, функция write возвращает ошибку EPIPE.

Листинг Д.1. Генерация SIGPIPE

//tcpcliserv/tsigpipe.c

 1 #include "unp.h"

 2 void

 3 sig_pipe(int signo)

 4 {

 5  printf("SIGPIPE received ");

 6  return;

 7 }

 8 int

 9 main(int argc, char **argv)

10 {

11  int sockfd;

12  struct sockaddr_in servaddr;

13  if (argc != 2)

14   err_quit("usage: tcpcli <Ipaddress>");

15  sockfd = Socket(AF_INET, SOCK_STREAM, 0);

16  bzero(&servaddr, sizeof(servaddr));

17  servaddr.sin_family = AF_INET;

18  servaddr.sin_port = htons(13); /* сервер времени и даты */

19  Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

20  Signal(SIGPIPE, sig_pipe);

21  Connect(sockfd, (SA*)&servaddr, sizeof(servaddr));

22  sleep(2);

23  Write(sockfd, "hello", 5);

24  sleep(2);

25  Write(sockfd, "world", 5);

26  exit(0);

27 }

5.7. В предположении, что узел сервера поддерживает модель системы с гибкой привязкой (см. раздел 8.8), все будет работать. Узел сервера примет IP-дейтаграмму (которая в данном случае содержит TCP-сегмент), прибывшую на самый левый канал, даже если IP-адрес получателя является адресом самого правого канала. Это можно проверить, если запустить наш сервер на узле linux (см. рис. 1.7), а затем запустить клиент на узле solaris, но на стороне клиента задать другой IP-адрес сервера (206.168.112.96). После установления соединения, запустив на стороне сервера программу netstat, мы увидим, что локальный IP-адрес является IP-адресом получателя из клиентского сегмента SYN, а не IP-адресом канала, на который прибыл сегмент SYN (как отмечалось в разделе 4.4).

5.8. Наш клиент был запущен в системе Intel с прямым порядком байтов, где 32-разрядное целое со значением 1 хранится так, как показано на рис. Д.1.

Рис. Д.1. Представление 32-разрядного целого числа 1 в формате прямого порядка байтов

Четыре байта посылаются на сокет в следующем порядке: A, A + 1, A + 2 и A + 3, и там хранятся в формате обратного порядка байтов, как показано на рис. Д.2.

Рис. Д.2. Представление 32-разрядного целого числа с рис. Д.1 в формате обратного порядка байтов

Значение 0x01000000 интерпретируется как 16 777 216. Аналогично, целое число 2, отправленное клиентом, интерпретируется сервером как 0x02000000, или 33 554 432. Сумма этих двух целых чисел равна 50 331 648, или 0x03000000. Когда это значение, записанное в обратном порядке байтов, отправляется клиенту, оно интерпретируется клиентом как целое число 3.

Но 32-разрядное целое число -22 представляется в системе с прямым порядком байтов так, как показано на рис. Д.3 (мы предполагаем, что используется поразрядное дополнение до двух для отрицательных чисел).

Рис. Д.3. Представление 32-разрядного целого числа -22 в формате прямого порядка байтов

В системе с обратным порядком байтов это значение интерпретируется как 0xeaffffff, или -352 521 537. Аналогично, представление числа -77 в прямом порядке байтов выглядит как 0xffffffb3, но в системах с обратным порядком оно представляется как 0xb3ffffff, или -1 275 068 417. Сложение, выполняемое сервером, приводит к результату 0x9efffffe, или -1 627 389 954. Полученное значение в обратном порядке байтов посылается через сокет клиенту, где в прямом порядке байтов оно интерпретируется как 0xfeffff9e, или -16 777 314 — это то значение, которое выводится в нашем примере.

5.9. Метод правильный (преобразование двоичных значений в сетевой порядок байтов), но нельзя использовать функции htonl и ntohl. Хотя символ l в названиях данных функций обозначает «long», эти функции работают с 32-разрядными целыми (раздел 3.4). В 64-разрядных системах long занимает 64 бита, и эти две функции работают некорректно. Для решения этой проблемы следует определить две новые функции hton64 и ntoh64, но они не будут работать в системах, представляющих значения типа long 32 битами.

5.10. В первом сценарии сервер будет навсегда блокирован при вызове функции readn в листинге 5.14, поскольку клиент посылает два 32-разрядных значения, а сервер ждет два 64-разрядных значения. В случае, если клиент и сервер поменяются узлами, клиент будет посылать два 64-разрядных значения, а сервер считает только первые 64 бита, интерпретируя их как два 32-разрядных значения. Второе 64-разрядное значение останется в приемном буфере сокета сервера. Сервер отправит обратно 32-разрядное значение, и клиент навсегда заблокируется в вызове функции readn в листинге 5.13, поскольку будет ждать для считывания 64-разрядное значение.

5.11. Функция IP-маршрутизации просматривает IP-адрес получателя (IP-адрес сервера) и пытается по таблице маршрутизации определить исходящий интерфейс и следующий маршрутизатор (см. главу 9 [111]). В качестве адреса отправителя используется первичный IP-адрес исходящего интерфейса, если сокет еще не связан с локальным IP-адресом.

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Глава 17 DNS

Из книги Linux автора Стахнов Алексей Александрович

Глава 17 DNS DNS – это Доменная Система Имен (Domain Name System). DNS преобразует символические имена машин в IP-адреса и наоборот – из IP-адреса в символическое имя. Для чего это нужно? Во-первых, человеку легче запомнить осмысленное имя – типа vasya.ru чем 195.66.195.42, а для компьютера проще


Глава 20 FTP

Из книги Linux и UNIX: программирование в shell. Руководство разработчика. автора Тейнсли Дэвид

Глава 20 FTP Эта глава посвящена протоколу FTP, настройке сервера FTP, проблемам конфигурации и безопасности сервера.Протокол FTPПротокол FTP (File Transfer Protocol, протокол передачи файлов) предназначен для передачи файлов в сети Интернет. Этот протокол был разработан на заре эры


ГЛАВА 14

Из книги автора

ГЛАВА 14 Переменные среды и интерпретатора shellЧтобы продуктивно работать с интерпретатором shell, нужно уметь управлять переменными этого интерпретатора. Переменными интерпретатора shell являются наименования, которым присваиваются значения. В качестве значений может


ГЛАВА 15

Из книги автора

ГЛАВА 15 Использование кавычекВ главе 14 обсуждались методы работы с переменными и операции подстановки. Чаще всего ошибки в использовании кавычек возникают при выполнении подстановок переменных в сценариях. Кавычки оказывают существенное влияние на формирование


ГЛАВА 16

Из книги автора

ГЛАВА 16 Понятие о shell–сценарииВ shell–сценарий может включаться одна или несколько команд; здесь нет общепринятых правил. Зачем же создавать целый сценарий ради двух–трех команд? Все зависит от предпочтений пользователя.В этой главе рассматриваются следующие


ГЛАВА 17

Из книги автора

ГЛАВА 17 Проверка условийПри создании сценария уточняется идентичность строк, права доступа к файлу или же выполняется проверка численных значений. На основе результатов проверки предпринимаются дальнейшие действия. Проверка обычно осуществляется с помощью команды test.


ГЛАВА 18

Из книги автора

ГЛАВА 18 Управляющие конструкцииВсе функциональные сценарии должны предлагать возможности по выбору возможных вариантов. При определенных условиях сценарии должны выполнять обработку списков. Этим вопросам посвящена настоящая глава. Кроме того, в ней описывается


ГЛАВА 19

Из книги автора

ГЛАВА 19 Функции интерпретатора shellДо сих пор весь программный код сценариев данной книги выполнялся последовательно от начала до конца программы. Подобный подход неплох, но при этом некоторые фрагменты кода, рассмотренного в наших примерах, дублируются в пределах


ГЛАВА 21

Из книги автора

ГЛАВА 21 Создание экранного выводаС помощью shell–сценариев можно создавать профессионального вида экраны, позволяющие реализовать интерактивное взаимодействие пользователя с системой. Для этого достаточно располагать цветным монитором и использовать команду tput.В


ГЛАВА 22

Из книги автора

ГЛАВА 22 Создание экранного вводаКогда речь идет об экранном вводе, или вводе данных, подразумевают ввод информации (в нашем случае с помощью клавиатуры), а затем — проверку достоверности введенных данных. Если данные удовлетворяют неким критериям, они


ГЛАВА 23

Из книги автора

ГЛАВА 23 Отладка сценариевОдной из самых сложных задач при создании shell–сценариев является их отладка. Желательно, чтобы пользователь, выполняющий эту задачу, получил консультации на данном этапе. Чтобы избежать распространенных ошибок, достаточно следовать указанному


ГЛАВА 24

Из книги автора

ГЛАВА 24 Встроенные команды интерпретатора shellВ предыдущих главах нам уже встречались конструкции, встроенные в интерпретатор shell Напомним, что речь идет о командах, которые не находятся в каталоге /bin или usr/bin, а встроены в интерпретатор Bourne shell. Скорость выполнения


ГЛАВА 25

Из книги автора

ГЛАВА 25 Дальнейшее изучение конструкции "документ здесь"При рассмотрении стандартного потока ввода и вывода, а также циклов while уже обсуждалась конструкция "документ здесь". Описывались методика пересылки электронной почты и способы формирования экранов меню, но


ГЛАВА 26

Из книги автора

ГЛАВА 26 Утилиты интерпретатора shellВ этой главе рассматриваются следующие темы:    • создание датируемых имен файлов и временных файлов;    • сигналы;   • команда trap и способы перехвата сигналов;   • команда eval;    • команда


ГЛАВА 28

Из книги автора

ГЛАВА 28 Сценарии уровня выполненияЕсли при загрузке системы вам нужно автоматически запустить приложение, службу или сценарий либо корректно завершить их работу при перезапуске системы, то необходимо создать сценарий уровня выполнения. Почти все варианты системы Linux, а


ГЛАВА 29

Из книги автора

ГЛАВА 29 Сценарии cgiВ настоящее время, когда практически на каждом ПК установлен Web–сервер, глава, посвященная сценариям cgi, органически вписывается в книгу по shell–программированию.В главе будут рассмотрены следующие темы:   • базовые сценарии cgi;   • использование