![](https://habrastorage.org/files/5b6/eda/336/5b6eda33666c425ba1729903945ac0c8.jpg)
Когда кому-то или чему-то становится плохо, то требуется нечто большее, чем просто констатация данного факта.
Первое — это диагностика проблемы, определение причин сбоя.
Взять и измерить давление, сделать пальпацию, проверить уровень масла в двигателе и так далее, и тому подобное.
А что если проблемы возникли при передаче данных в интернет/интранет-сети?
Тут, по-видимому, потребуются особые средства диагностики.
В особенности будут полезны средства, которые позволяют проводить статистический анализ большого количества данных.
Существует множество разных инструментов.
Часть из них можно найти в такой замечательной программе, как Wireshark.
В меню Statistics (Статистика) Wireshark представлен богатый набор функциональности.
При этом результаты могут представляться не только в общем, но и графическом виде.
Как раз о графическом виде и хочется поговорить.
Рассказать о наборе из пяти графиков статистики TCP StreamGraph.
Позволяют легко и эффективно проводить анализ и диагностику TCP-соединений.
Но прежде чем начинать говорить о графиках, для их лучшего понимания рассмотрим основы теории TCP.
Минимум, необходимый для общего понимания TCP StreamGraph
- TCP (Transmission Control Protocol) — протокол транспортного уровня, отвечающий за гарантированную доставку данных от одного узла сети к другому. Поверх TCP работают протоколы прикладного уровня, такие как HTTP, FTP, SMTP, TELNET и другие.
- Гарантированность доставки в TCP достигается за счет использования механизмов подтверждений и повторов.
После передачи порции данных отправитель ждет подтверждения от получателя о доставке. Если подтверждение не приходит, выполняется повторная отправка.
- Данные, подлежащие отправке, на уровне TCP представляются потоком байт, где каждый байт последовательно пронумерован. TCP делит поток на части — сегменты — и передает их на более низкий (сетевой) уровень для отправки получателю. В заголовке сегмента указывается его номер (Sequence number, Seq) — номер первого байта сегмента в общем потоке.
- Получатель принимает сегменты и собирает из них исходный непрерывный поток байт, отправляет подтверждения.
В заголовке указывает номер подтверждения (Acknowledgment number, Ack) — порядковый номер следующего сегмента, ожидаемого от отправителя. Значение Ack означает, что вся непрерывная последовательность байт с первого до Ack-1 приняты успешно. Согласно спецификации, подтверждение для каждого сегмента не требуется. Одно подтверждение может отправляться сразу на несколько полученных сегментов.
- Получатель не только подтверждает входящие данные, но и управляет интенсивностью их поступления.
В заголовке подтверждения указывается размер окна приема (Window, Win).
Отправитель передает сегменты с данными, объем которых не превышает размера Win.
Если получатель сообщает о нулевом Win, передача данных приостанавливается, пока не будет указан больший размер.
- Передаче данных между двумя сетевыми приложениями предшествует установка TCP-соединения.
По завершении обмена соединение закрывается.
Соединение уникально идентифицируется парой значений IP-адреса хоста, номер порта приложения.
Приложение, инициирующее соединение (клиент), каждый раз получает в ОС произвольный номер порта и освобождает его после завершения сеанса передачи данных.
Приложение, ожидающее соединений (сервер), всегда использует постоянный номер порта, пока не завершит свою работу.
Ниже приведена картинка с частным случаем TCP обмена данных.
Следует рассматривать как упрощенный вариант.
В примере, нумерация сегментов начинается с единицы.
Хотя в действительности это не совсем так.
Однако то же самое показывает и Wireshark при дефолтных настройках.
Отправитель шлет два сегмента (Seq=1 и Seq=6), содержащих по пять байт данных каждый.
Получатель отвечает, что все байты до 10 получены успешно и ожидается следующий 11-й сегмент (Ack=11).
Отправитель передает еще два (Seq=11 и Seq=16), один из которых теряется в сети (Seq=11).
Получатель констатирует, что в потоке принятых данных возник разрыв.
Сообщает, что начиная с первого байта непрерывно приняты только 10 байт и он по-прежнему ждет 11-й сегмент (Ack=11).
Однако одновременно с этим в подтверждающем сегменте указывает SACK (Selective acknowledgment, выборочное подтверждение) блок, с диапазоном байт, полученных после разрыва. Благодаря SACK отправитель повторно передаст только пропавший сегмент (Seq=11). Без SACK потребовалось бы повторять Seq=16 тоже. Использование SACK должно поддерживаться обеими сторонами обмена.
![](https://habrastorage.org/files/0b0/68d/27e/0b068d27eb264894a3772206dd4ec997.png)
А теперь рассмотрим процесс передачи данных в TCP-соединении через TCP StreamGraph в Wireshark.
Однако, чтобы не описывать графики просто так, сделаю это на простом и понятном примере.
Загружу файл с тестового сервера на свой компьютер, используя протокол HTTP.
Для этого воспользуюсь утилитой curl, а не веб-браузером.
curl поможет создать некоторые проблемы, которые увидим на графиках.
Проблемы возникнут вследствие того, что загрузка будет вестись напрямую в консоль, а не в файл.
Итак, запускаю Wireshark, включаю захват трафика.
Загружаю утилитой curl тестовый файл размером 10Мб с сервера v4.speedtest.reliableservers.com (10MBtest.bin).
curl 'http://v4.speedtest.reliableservers.com/10MBtest.bin'
![](https://habrastorage.org/files/ac8/4f1/7a4/ac84f17a44db47f38f20dc8a6439b1e8.png)
Останавливаю захват трафика.
В полученном сетевом дампе Wireshark ищу HTTP пакет с GET запросом файла 10MBtest.bin и определяю номер TCP–соединения, в котором он загружался. Или ищем по фильтру tcp contains "10MBtest.bin".
![](https://habrastorage.org/files/78a/cb2/d94/78acb2d949a441dc8503f9628e866632.png)
Фильтрую весь трафик по номеру TCP-соединения в котором загружался тестовый файл tcp.stream==5.
![](https://habrastorage.org/files/9cb/7ad/58f/9cb7ad58fdbb47d58e23b12cbf1eed01.png)
А вот теперь смотрим TCP StreamGraph.
Важно знать, что все графики из TCP StreamGraph строятся по одному TCP соединению и являются направленными.
Направление указывает, в какую сторону двигался анализируемый поток данных от клиента к серверу или наоборот.
Направление и соединение определяется по пакету, выбранному в интерфейсе Wireshark.
В случае приведенного выше примера выбираю любой пакет из соединения, в котором загружался тестовый файл 10MBtest.bin.
Направление было от сервера к клиенту, поэтому Source пакета должно соответствовать IP-адресу сервера.
Все графики находятся в Wireshark меню Statistics --> TCP StreamGraph.
Time-Sequence Graph (Stevens)
![](https://habrastorage.org/files/60e/c72/7e1/60ec727e1b464e2dae1258e78df16ac9.png)
Time-Sequence Graph (Stevens) выглядит как наклонная кривая, состоящая из точек.
Координаты каждой точки графика — это значение Sequence number TCP сегмента (ось Y — Байты) и время его захвата (ось X — секунды).
Соответственно, как говорилось ранее, учитываются только сегменты с данными одного TCP-соединения, перемещавшиеся в определенном направлении, от серверу к клиенту (загрузка, download) или наоборот (выгрузка, upload).
Согласно теории Sequence number, это номер первого байта данных сегмента в общем потоке данных.
Поэтому можно сказать, что график показывает динамику загрузки/выгрузки байт данных в TCP соединении по времени.
На любом участке легко рассчитывается скорость передачи данных, (Sequence number деленная на Time, получаем Байт/сек).
Как следствие, по изменениям наклона участков кривой можно судить об изменениях скорости передачи данных.
В идеальных условиях график выглядит как диагональная линия с большим углом наклона.
Однако на практике это не всегда так.
По аномалиям на кривой графика можно выявить задержки в передаче данных, потери сегментов и их повторные отправки (Retransmission).
На приведенном ниже примере графика во время загрузки файла возникли две схожие проблемы с остановкой передачи данных и потерей сегментов.
![](https://habrastorage.org/files/be7/c3e/b31/be7c3eb3128e40b3b6e779f8ab603f37.png)
Горячие клавиши в Windows (краткая справка):
Пошаговое увеличение или уменьшение масштаба графика выполняется через клавиши i/o или прямым выделением участка мышью. Возврат к исходному масштабу, клавиша Home.
Пробел — превращает курсор в перекрестие с вертикальной и горизонтальной вспомогательными линиями.
Цифровые клавиши с 1 по 5 — выбор другого графика из набора.
Ctrl + правая кнопка мыши — появляется окно с увеличенным изображением участка графика из под курсора.
Щелчок мышки на любой точке графика приводит к переходу в интерфейсе Wireshark на соответствующий ей TCP пакет.
Time-Sequence Graph (tcptrace)
![](https://habrastorage.org/files/534/aff/eca/534affeca8b64900856ed4bc3c96e59c.png)
По внешнему виду Time-Sequence Graph (tcptrace) напоминает предыдущий график и предназначен для более полного анализа возможных проблем. В нем все так же выводятся значения Sequence number сегментов потока данных на временной шкале.
Однако добавился еще один атрибут сегмента — его размер (TCP Segment Len).
Поэтому сегменты отображаются уже не точками, а вертикальными отрезками с засечками на концах, как английская буква I — «ай». Основание отрезка это Sequence number, а длина — размер сегмента в байтах.
Также на графике выводится информация из обратного потока подтверждающих сегментов, Window (Win), Acknowledgment number (Ack) и SACK. Значения Ack отображаются ступенчатой кривой, проходящей ниже сегментов данных.
Каждая ступень, ее вершина — это момент времени прихода подтверждения об общем количестве непрерывно принятых байт получателем.
Аналогично “ступенчато” отображается размер окна принимающей стороны Win.
Кривая проходит выше потока данных.
Вершина ступени — это сумма значений Ack и Win подтверждающего сегмента.
![](https://habrastorage.org/files/163/036/c97/163036c975a34783ab968541bd148e73.png)
Синими вертикальными линиями визуализируются SACK блоки.
SACK может присутствовать в подтверждении, если в сплошном потоке полученных данных возникли разрывы.
Синяя линия — это диапазон байт полученных после разрыва.
![](https://habrastorage.org/files/8ed/4a9/b0b/8ed4a9b0bd9a48c2a0d9deca48cb9b32.png)
В общем виде график представляет собой “коридор” из двух ступенчатых кривых, внутри которого перемещаются сегменты с данными. Сужение «коридора» говорит об уменьшении размера окна приема (Win), расширение — об обратном.
На предыдущем графике были обнаружены две проблемы с остановкой передачи данных.
Time-Sequence Graph (tcptrace) внес ясность в причины случившегося.
Уменьшился размер окна (Win) на принимающей стороне.
Отправитель передал максимально допустимое количество сегментов с данными, чтобы не переполнить окно, и остановился.
После того, как получатель сообщил об увеличении размера окна (Window Update), передача данных возобновилась.
![](https://habrastorage.org/files/894/3ba/bb4/8943babb44964e37b97945c52548e2d4.png)
Throughput Graph
![](https://habrastorage.org/files/bdc/07e/e30/bdc07ee30e8d4ab0990a4f9b86c156ac.png)
Throughput Graph выглядит как множество точек, иногда расположенных весьма хаотично.
Координаты каждой точки — это расчетная скорость перемещения сегмента в потоке данных (ось Y — Байт/сек) и время его захвата (ось X — секунды).
Если быть точным, для сглаживания колебаний на графике фиксируются не реальные, а усредненные значения скорости.
Используется усредняющая функция скользящего среднего (Moving Average, MA) на 20 значений за предыдущий период.
По коду Wireshark, средняя скорость N-го сегмента равна сумме длин всех сегментов от N до N-20, деленная на дельту по времени между их захватом.
Как следствие, две задержки в передаче данных, вызванные уменьшением размера окна (Win), привели к падению Throughput в проблемные моменты времени. В остальное время скорость закачки варьировалась в пределах диапазона от 1.4 до 3.4 МБайт.
![](https://habrastorage.org/files/544/d45/bb3/544d45bb33ab4478acecb5b0204bee82.png)
Round Trip Time Graph
Round Trip Time (RTT) — это время, прошедшее между отправкой сегмента с данными и получением подтверждения о его успешной доставке.
![](https://habrastorage.org/files/927/431/8dd/9274318dde1e412083e4ac06308130cf.png)
Round Trip Time Graph показывает RTT (ось Y — секунды) по каждому сегмента из потока данных.
Идентификатором сегмента выступает его Sequence number (ось X — Байты).
![](https://habrastorage.org/files/d4f/c54/4ee/d4fc544ee14a45e2a2470ccbb835fde4.png)
При нормальных условиях большая часть точек концентрируется в нижней части графика.
В примере RTT почти все время не превышает 0.1 сек., за исключением проблемных моментов, когда RTT подскакивала до 0.4 сек.
Все графики связаны между собой формулой Throughput = Window size / RTT
![](https://habrastorage.org/files/51c/2c3/41f/51c2c341f27c4131aafb9961ed0cebbf.png)
Window Scaling Graph
![](https://habrastorage.org/files/b65/9a6/d0c/b659a6d0c96e45dd8cea10d21175c46d.png)
Координаты каждой точки Window Scaling Graph — это размер окна Windowsize (ось Y — Байты) сегмента на момент времени его захвата (ось X — секунды).
В текущем графике направленность изменена на обратную потоку данных (клиент --> сервер). В нем анализируются только подтверждающие сегменты.
В Window Scaling Graph присутствует информация о двех проблемных случаях сокращения размера окна до критичных размеров.
Это полностью подтверждает показаниями на Time-Sequence Graph.
![](https://habrastorage.org/files/0ab/564/2d0/0ab5642d0d5f4bcf96b24933bbbeac1a.png)
Заключение
Ну вот, кажется, и все. Что хотел — сказал.
Информации по теме гораздо больше. В статье были изложены только основы, помогающие лучше понять графики из TCP StreamGraph, Wireshark.
Эти графики очень полезны в своем практическом применении и позволяют делать всесторонний обзор любого TCP-соединения, выявлять сетевые проблемы.
Конечно, есть и другие инструменты, подобные TCP StreamGraph, например, tcptrace, captcp.
Не стоит забывать и о IO Graph того же Wireshark. Он обладает более обширной функциональностью выходящей далеко за пределы TCP StreamGraph.
Надеюсь, статья окажется полезна всем тем, кто интересуется сетевыми технологиями или изучает протокол TCP.