Ещё в мае 2012 года я начал небольшой R&D проект по созданию сетевого протокола для нужд MMORPG с no-target системой боя. Теоретическая часть была почти закончена ещё в 2012 году, но дальше проект был заморожен из-за наличия более приоритетных задач. И вот в начале декабря 2015 года работы над ним были возобновлены.
Ещё с 2012 года была идея применить тот или иной метод помехоустойчивого кодирования к передаваемым данным для борьбы с потерей пакетов. Чисто интуитивно я считал, что чаще всего теряются одиночные пакеты, а не их группы, но это предположение ещё предстояло проверить. А потому, перед тем, как приступать к написанию черновой реализации протокола и прототипа для его тестирования и отладки, я решил провести тестирование своего интернет канала на предмет того, как же на самом деле обстоят дела с такими вещами как потеря пакетов, их дублирование и нарушение порядка передачи. Т.к. протокол разрабатывается для использования в стационарных сетях (ни о каких мобильных соединениях речи идти не могло по множеству причин), то своё подключение (крупный город, но не столица, потребительская сеть, абонплата менее 10$ в месяц) я посчитал вполне релевантным для такого теста.
Исходя из предполагаемых характеристик протокола для тестирования был выбран следующий сценарий: в течении суток клиент каждую миллисекунду отправляет серверу пакет, а сервер при получении пакета сразу же отправляет его назад (тестировались пакеты размером 60 и 1276 байт – размеры с учётом IP-заголовка). Хотя в таком сценарии потери от сервера к клиенту отображали ещё и потери от клиенту к серверу, но, основываясь на своей интуиции, я решил, что этим можно будет пренебречь, т.к. кол-во потерь будет разниться даже не в разы, а на порядки. Тестирование проводилось дважды: в будний день (вторник, среда или четверг) и в выходной (воскресенье).
Первая вещь, которую показали тесты, это полное отсутствие дублирования или нарушения порядка приёма пакетов. Если отсутствие дублирования нам мало что говорит (проверку-то всё равно придётся делать, хотя бы из-за возможности использования дублирования пакетов для атаки на сервер), то вот жесткий порядок приёма – это весьма важно. Фокус в том, что даже если он и нарушается, то очень-очень редко, а значит, для упрощения протокола его можно трактовать просто как потерю пакета (логика обработки: если пришёл пакет с номером, равным или меньшим чем последний принятый – отбрасываем его).
Однако, кроме отсутствия дублирования и перестановки пакетов в глаза бросалась ещё одна вещь – разброс между минимальными и максимальными значениями RTT в течении минуты очень часто превышал 30мс. При этом на графике линия среднего значения RTT была очень близко к линии минимального значения. Дальнейшее исследования этой аномалии показало, что строго раз в 120 секунд передача прерывается на 32мс, после чего все непереданные пакеты передаются одномоментно. Небольшое расследование показало, что причиной такого странного поведения стал мой домашний роутер – ASUS RT-N66U. Сразу после того, как подозрения пали на него, я провёл тест на базе резервного D-Link DIR-825 и получил куда более нормальные результаты. Хотя ни один из этих роутеров хорошим я назвать не могу.
Если у меня будет время, то в будущем я планирую провести недельный тест на серверном оборудовании с обеих сторон, чтобы получить более точные данные о самом канале.
Размер пакетов и день недели фактически не оказывают влияние на пинг, в отличии от времени суток.Теперь пришло время перейти к анализу самых важных для нас характеристик: количества и структуры потерь пакетов в обоих направлениях. Чтобы не захламлять пост графиками просто приведу ряд наблюдений:
- Пакеты размером в 60 байт теряются примерно в 3-4 раза реже, чем пакеты размером 1276 байт
- В выходной день потери примерно в 3 раза выше, чем в будний
Далее будем работать с информацией о потерях пакетов размером 1276 байт в выходной день (как самым худшим случаем). Посмотрим на график потерь пакетов (на графике отфильтрованы пропадания связи длительностью более секунды).
Картина довольно красноречива: потери есть, но их не так уж и много. От сервера к клиенту теряется до 800 пакетов из 60000 в самый пик нагрузки на сеть, т.е. до 1.33%. Потери от клиента к серверу вообще не превышают 0.041%.
Теперь попробуем разбить все потери пакетов при передаче от сервера к клиенту на группы, основываясь на количестве последовательно потерянных пакетов (интервалы более 1000 пакетов или секунды реального времени рассматриваются как кратковременная потеря интернет соединения):
Размер группы | Кол-во групп | % групп | Кол-во пакетов | % пакетов |
1 пакет | 141663 | 97.3490 | 141663 | 94.2988 |
2 пакета | 3703 | 2.5452 | 7406 | 4.9309 |
3 пакета | 125 | 0.0859 | 375 | 0.2497 |
4 пакета | 13 | 0.0089 | 52 | 0.0345 |
не более 20 | 5 | 0.0034 | 38 | 0.0253 |
не более 40 | 7 | 0.0048 | 270 | 0.1798 |
не более 60 | 1 | 0.0007 | 50 | 0.0333 |
не более 80 | 0 | 0.0000 | 0 | 0.0000 |
не более 100 | 1 | 0.0007 | 99 | 0.0659 |
не более 120 | 1 | 0.0007 | 101 | 0.0672 |
не более 1000 | 1 | 0.0007 | 172 | 0.1145 |
Исходя из полученных данных моё изначальное предположение полностью подтвердилось. Я даже сам не ожидал, что более 94% все потерь придётся на одиночные потери.