├── .gitignore ├── assets ├── ipmtu.png ├── rwnd.png ├── osi_model.png ├── tcpswretrans.png ├── window_probe.png ├── sliding_window.png ├── tcpstreamsegment.png ├── osi_vs_tcpip_model.png └── tcp_ip_data_encapsulation.png ├── .editorconfig ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ -------------------------------------------------------------------------------- /assets/ipmtu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity182/Computer-Networks/HEAD/assets/ipmtu.png -------------------------------------------------------------------------------- /assets/rwnd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity182/Computer-Networks/HEAD/assets/rwnd.png -------------------------------------------------------------------------------- /assets/osi_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity182/Computer-Networks/HEAD/assets/osi_model.png -------------------------------------------------------------------------------- /assets/tcpswretrans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity182/Computer-Networks/HEAD/assets/tcpswretrans.png -------------------------------------------------------------------------------- /assets/window_probe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity182/Computer-Networks/HEAD/assets/window_probe.png -------------------------------------------------------------------------------- /assets/sliding_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity182/Computer-Networks/HEAD/assets/sliding_window.png -------------------------------------------------------------------------------- /assets/tcpstreamsegment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity182/Computer-Networks/HEAD/assets/tcpstreamsegment.png -------------------------------------------------------------------------------- /assets/osi_vs_tcpip_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity182/Computer-Networks/HEAD/assets/osi_vs_tcpip_model.png -------------------------------------------------------------------------------- /assets/tcp_ip_data_encapsulation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity182/Computer-Networks/HEAD/assets/tcp_ip_data_encapsulation.png -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Documentation config 2 | root = true 3 | 4 | [*.{md,MD}] 5 | trim_trailing_whitespace = true 6 | indent_style = space 7 | indent_size = 4 8 | insert_final_newline = true 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Dmitry 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Помощник в освоении компьютерных сетей 2 | 3 |

[Операционные системы] | [Компьютерные сети] | [I/O и сетевое программирование]

4 | 5 | **Содержание:** 6 | - [Internet protocol suite (TCP/IP)](#internet-protocol-suite-tcpip) 7 | - [OSI Model](#osi-model) 8 | - [PDU, SDU](#pdu-sdu) 9 | - [MTU](#mtu) 10 | - [IP Fragmentation](#ip-fragmentation) 11 | - [Tradeoffs](#tradeoffs) 12 | - [MTU Path Discovery](#mtu-path-discovery) 13 | - [TCP/UDP](#tcpudp) 14 | - [TCP](#tcp) 15 | - [UDP](#udp) 16 | - [Отличия TCP от UDP](#отличия-tcp-от-udp) 17 | - [TCP Fundamentals](#tcp-fundamentals) 18 | - [Streams, Segments, MSS и Sequence Numbers](#streams-segments-mss-и-sequence-numbers) 19 | - [MSS](#mss) 20 | - [Sequence Numbers](#sequence-numbers) 21 | - [Установка соединения (Handshake)](#установка-соединения-handshake) 22 | - [SYN Flood](#syn-flood) 23 | - [TCP Sliding window Acknowledgement system](#tcp-sliding-window-acknowledgement-system) 24 | - [Flow Control](#flow-control) 25 | - [Порядок и надежность данных, Retransmission, Multiple Segments Acknowledgment](#порядок-и-надежность-данных-retransmission-multiple-segments-acknowledgment) 26 | - [Congestion](#congestion) 27 | - [Адресация пакетов](#адресация-пакетов) 28 | - [\[Link layer\] MAC](#link-layer-mac) 29 | - [MAC Address](#mac-address) 30 | - [\[Internet Layer\] IP](#internet-layer-ip) 31 | - [IP Address](#ip-address) 32 | - [Версии IP](#версии-ip) 33 | - [IP: Подсети (Subnetworks)](#ip-подсети-subnetworks) 34 | - [Анализ подсети](#анализ-подсети) 35 | - [Пример разделения на подсети](#пример-разделения-на-подсети) 36 | - [Публичные и приватные IP адреса](#публичные-и-приватные-ip-адреса) 37 | - [Loopback Interface](#loopback-interface) 38 | - [Маршрутизация](#маршрутизация) 39 | - [Ресурсы и источники](#ресурсы-и-источники) 40 | 41 | --- 42 | 43 | ## Internet protocol suite (TCP/IP) 44 | 45 | **[Internet protocol suite](https://en.wikipedia.org/wiki/Internet_protocol_suite)** - это концептуальная модель и набор протоколов используемых в интернете и похожих компьютерных сетях. Эта модель наиболее известна как **TCP/IP** потому что в ее основе лежат именно TCP и IP. 46 | 47 | Модель описывает способ передачи данных от источника информации к получателю (end-to-end data communication). Модель предполагает прохождение через четыре уровня абстракции, которые классифицируют все используемые протоколы в зависимости от их зоны ответственности и объема задействованных сетей. 48 | 49 | Эти уровни с самого высокого до низкого: 50 | - **\[Layer 4\] Прикладной (Application)** - способ передачи данных между процессами для приложений 51 | - Протоколы: HTTP, FTP, SMTP, SSH, DNS. Эти протоколы работают поверх TCP или UDP и привязаны к определенному порту 52 | - **\[Layer 3\] Транспортный (Transport)** - способ передачи данных от одного хоста к другому. На этом уровне могут решаться проблемы потери сообщений, а также гарантироваться правильный порядок прихода пакетов. Также на этом уровне определяется, для какого именно приложения верхнего уровня предназначены данные. Для этого используется специальное число, называемое *портом* 53 | - Протоколы: TCP, UDP 54 | - **\[Layer 2\] Сетевой (Internet; Network)** - описывает способ передачи данных из одной сети в другую. На этом уровне работают маршрутизаторы, которые перенаправляют пакеты в нужную сеть путем расчета адреса сети по маске сети 55 | - Протоколы: IP, ICMP 56 | - **\[Layer 1\] Канальный (Link; Network Interface)** - описывает способ передачи данных между девайсами на физическом уровне в рамках одного сегмента сети 57 | - Протоколы: Ethernet, IEEE 802.11 58 | 59 | --- 60 | 61 | ## OSI Model 62 | 63 | [OSI Model](https://en.wikipedia.org/wiki/OSI_model) - это устаревшая модель. В современном мире все говорят только о TCP/IP, поэтому рассматривать эту модель подробно мы не будем. 64 | 65 | OSI модель имеет 7 уровней: 66 | 67 | ![OSI Model](assets/osi_model.png) 68 | 69 | Вот как соотносятся уровни TCP/IP и OSI: 70 | 71 | ![OSI vs TCP model comparison](assets/osi_vs_tcpip_model.png) 72 | 73 | --- 74 | 75 | ## PDU, SDU 76 | 77 | Данные в TCP/IP передаются от верхнего уровня к нижнему и каждый уровень должен обслужить данные свыше. Пример инкапсуляции данных при прохождении через уровни TCP/IP: 78 | 79 | ![tcp-ip data encapsulation](assets/tcp_ip_data_encapsulation.png) 80 | 81 | Здесь существуют такие понятия как PDU и SDU: 82 | - **PDU (Protocol Data Unit)** - это конечное сообщение, которым оперирует определенный уровень N. Однако, когда это сообщение передается на уровень ниже (N-1), оно становится SDU для этого нижнего уровня 83 | - **SDU (Service Data Unit)** - это данные, переданные от верхнего уровня (N + 1), которые должен обслужить уровень N. 84 | 85 | То есть, каждый уровень просто оборачивает данные, полученные свыше, в свою структуру, добавляя необходимые хэдеры. 86 | 87 | ### MTU 88 | 89 | *MTU (Maximum Transmission Unit)* - это максимальный размер PDU, который может обслужить другой хост на каком-либо уровне TCP/IP. 90 | 91 | Когда мы говорим о MTU, обычно мы имеем в виду только *IP Layer*, если не сказано обратное. 92 | 93 | *Минимальное значение MTU*, заданное стандартом для протокола IP, равно 576 байт, поэтому гарантируется, что каждая сеть минимально может обработать пакет такого размера. 94 | 95 | ### IP Fragmentation 96 | 97 | Если общий размер IP пакета вместе с хэдерами больше MTU, то при передаче от сети с высоким MTU к сети с низким MTU, это сообщение фрагментируется в несколько IP фрагментов. 98 | 99 | Фрагментация IP датаграмм: 100 | 101 | ![IP Fragmentation](assets/ipmtu.png) 102 | 103 | Фрагментация плохая тем, что: 104 | 1. Увеличивает нагрузку на сеть из-за большего количества пакетов 105 | 2. Увеличивает overhead, так как вместо одного пакета с хэдерами появляется несколько с идентичными хэдерами 106 | 107 | ### Tradeoffs 108 | 109 | - Большие MTU означают меньший overhead 110 | - Меньшие значения MTU означают меньший network delay 111 | 112 | Выдержка из Вики по трейдоффам при выборе размера MTU: 113 | > A larger MTU brings greater efficiency because each network packet carries more user data while protocol overheads, such as headers or underlying per-packet delays, remain fixed; the resulting higher efficiency means an improvement in bulk protocol throughput. A larger MTU also requires processing of fewer packets for the same amount of data. In some systems, per-packet-processing can be a critical performance limitation. 114 | > 115 | > However, this gain is not without a downside. Large packets occupy a slow link for more time than a smaller packet, causing greater delays to subsequent packets, and increasing network delay and delay variation. For example, a 1500-byte packet, the largest allowed by Ethernet at the network layer, ties up a 14.4k modem for about one second. 116 | > 117 | > Large packets are also problematic in the presence of communications errors. If no forward error correction is used, corruption of a single bit in a packet requires that the entire packet be retransmitted, which can be costly. At a given bit error rate, larger packets are more susceptible to corruption. Their greater payload makes retransmissions of larger packets take longer. Despite the negative effects on retransmission duration, large packets can still have a net positive effect on end-to-end TCP performance. 118 | 119 | ### MTU Path Discovery 120 | 121 | **MTU Path Discovery** - это процесс определения значения MTU на другой стороне сети. Нам требуется такой механизм, так как изначально сеть не знает значения MTU другой стороны, а также потому, что нам важно подобрать оптимальное значение MTU. 122 | 123 | По возможности мы хотим иметь как можно большее MTU, так как чем больше IP датаграмма, тем больше мы можем передать полезных данных с минимальным overhead, удовлетворяющее обе сети, чтобы повысить производительность и избежать фрагментации данных. 124 | 125 | --- 126 | 127 | ## TCP/UDP 128 | 129 | ### TCP 130 | 131 | **TCP** - это гарантированный транспортный механизм с предварительной установкой соединения (рукопожатия - handshake), предоставляющий приложению надежный поток данных и дающий гарантию в безошибочности получаемых данных. TCP имеет механизм для регулирования нагрузки на сеть. Более того, TCP гарантирует что полученные данные пришли в том же порядке, в котором были отправлены другим хостом. 132 | 133 | ### UDP 134 | 135 | **UDP (User Datagram Protocol)** - протокол передачи пакетов (называемыми датаграммами) без необходимости предварительной установки соединения. UDP в целом испольует простую модель данных, без обеспечения надежности, упорядочивания и целостности данных. Можно сказать, это самый протокол в семействе TCP/IP. Все, что он делает - это берет данные с прикладного уровня, упаковывает их в простой формат данных и передает в IP для передачи по сети. 136 | 137 | Природа UDP как протокола без сохранения состояния также полезна для серверов, отвечающих на небольшие запросы от огромного числа клиентов, например DNS и потоковые мультимедийные приложения вроде IPTV, Voice over IP, протоколы туннелирования IP и многие онлайн-игры. Главная особенность этих приложений состоит в том, что старые сообщения очень быстро становятся бесполезными, поэтому лучше получить новое сообщение, чем пытаться переслать старое, а создание соединения занимает больше ресурсов, чем повторная отправка. 138 | 139 | Но если TCP имеет механизм для контроля нагрузки на сеть (лимит сообщений), то UDP нет. Чувствительные к перегрузкам UDP-приложения, которые потребляют значительную часть доступной пропускной способности, могут поставить под угрозу стабильность сети. 140 | 141 | Сетевые механизмы были предназначены для того, чтобы свести к минимуму возможные эффекты от перегрузок при неконтролируемых, высокоскоростных нагрузках. Такие сетевые элементы, как маршрутизаторы, использующие пакетные очереди и техники сброса, часто являются единственным доступным инструментом для замедления избыточного UDP-трафика. Однако большинство приложений на самом деле контролируют нагрузку на прикладном уровне. 142 | 143 | *DCCP (англ. Datagram Congestion Control Protocol — протокол контроля за перегрузками датаграмм)* разработан как частичное решение этой потенциальной проблемы с помощью добавления конечному хосту механизмов для отслеживания перегрузок для высокоскоростных UDP-потоков вроде потоковых медиа. 144 | 145 | ### Отличия TCP от UDP 146 | 147 | Все отличия TCP от UDP. 148 | 149 | **TCP:** 150 | 151 | - Надёжность — TCP управляет подтверждением, повторной передачей и тайм-аутом сообщений. Производятся многочисленные попытки доставить сообщение. Если оно потеряется на пути, сервер вновь запросит потерянную часть. В TCP нет ни пропавших данных, ни (в случае многочисленных тайм-аутов) разорванных соединений. 152 | - Упорядоченность — если два сообщения последовательно отправлены, первое сообщение достигнет приложения-получателя первым. Если участки данных прибывают в неверном порядке, TCP отправляет неупорядоченные данные в буфер до тех пор, пока все данные не могут быть упорядочены и переданы приложению. 153 | - Тяжеловесность — TCP необходимо три пакета для установки сокет-соединения перед тем, как отправить данные. TCP следит за надёжностью и перегрузками. 154 | - Потоковость — данные читаются как поток байтов, не передается никаких особых обозначений для границ сообщения или сегментов. 155 | 156 | **UDP:** 157 | 158 | - Ненадёжный — когда сообщение посылается, неизвестно, достигнет ли оно своего назначения — оно может потеряться по пути. Нет таких понятий, как подтверждение, повторная передача, тайм-аут. 159 | - Неупорядоченность — если два сообщения отправлены одному получателю, то порядок их достижения цели не может быть предугадан. 160 | - Легковесность — никакого упорядочивания сообщений, никакого отслеживания соединений и т. д. Это небольшой транспортный уровень, разработанный на IP. 161 | - Датаграммы — пакеты посылаются по отдельности и проверяются на целостность только если они прибыли. Пакеты имеют определенные границы, которые соблюдаются после получения, то есть операция чтения на сокете-получателе выдаст сообщение таким, каким оно было изначально послано. 162 | - Нет контроля перегрузок — UDP сам по себе не избегает перегрузок. Для приложений с большой пропускной способностью возможно вызвать коллапс перегрузок, если только они не реализуют меры контроля на прикладном уровне. 163 | 164 | --- 165 | 166 | ## TCP Fundamentals 167 | 168 | Здесь разберу более подробно устройство TCP протокола. 169 | 170 | ### Streams, Segments, MSS и Sequence Numbers 171 | 172 | Важно отметить, что TCP является *стриминговым (stream)* протоколом, в отличие от UDP, который оперирует отдельными блоками данных. Но в TCP нет разделения данных - сокет принимает просто поток байтов и передает их на другую сторону соединения, где они будут уже преобразованы в необходимую структуру и прочитаны. 173 | Это позволяет избежать создания чанков (chunk) на стороне приложения, когда они сами по себе не имеют смысла, а являются частью большого объекта. 174 | 175 | Конечно же, TCP не может взять и передать весь поток байтов за один раз. Более того, нижний уровень (сетевой) - IP - не является стриминговым, а оперирует отдельными сообщениями. Для этого TCP разбивает поток данных на *сегменты (segments)*. 176 | 177 | ![TCP Stream](assets/tcpstreamsegment.png) 178 | 179 | ### MSS 180 | 181 | Здесь также существует такой термин как *MSS (Maximum Segment Size)* - максимальный размер сегмента. Он задается при установке соединения. Если receiver может байт меньше, чем MSS, то сегмент не должен превышать значение на стороне receiver-а. 182 | 183 | На самом деле, этот термин немного путает - в действительности MSS обозначает количество данных, которые могут упаковаться в сегмент и не учитывает TCP хэдеры. Например, если MSS равен 100, то TCP сегмент может быть размером 120 байт или больше. 184 | 185 | Выбор MSS основывается в основном на следующих факторах: 186 | - Overhead Management - TCP хэдер забирает 20 байт (или больше), IP хэдер также забирает 20 байт. это означает что минимум 40 байт требуется для хэдеров, и эти байты, не являющиеся полезной нагрузкой (payload), по сути являются overhead так как посылаются в каждом сегменте. Если установить MSS слишком низким - допустим, 40 байт, - то максимум 50% размера пакета могут быть полезными данными - а остальное просто headers. 187 | - IP Fragmentation - TCP сегменты упаковываются в IP пакеты. IP пакеты также имеют свои проблемы связанные с максимальным размером пакета - вспоминаем MTU и фрагментацию. Фрагментация снижает эффективность и повышает риски потери TCP сегмента, что выливается в то, что весь сегмент придется пересылать. 188 | 189 | *Дефолтное значение MSS* - это 536. Оно получается путем вычитания 40 байт (TCP хэдеры + IP хэдеры) из значения минимального MTU (576). 190 | 191 | Устройства могут использовать более высокое значение MSS, если они уверены в том, что MTU сетей могут пересылать пакеты больше 576 байт. Для определению оптимального значения MSS, в свою очередь, используется процесс MTU Path Discovery. 192 | 193 | ### Sequence Numbers 194 | 195 | Да, TCP воспринимает данные как поток байтов, однако нам требуется идентификация байтов посланных в пакетах (сама же идентификация требуется для отслеживания данных, которые сокет получает от приложения, чтобы обеспечить гарантию что они будут получены receiver-ом). Для этого в хэдере задается *Sequence Number* - порядковый номер первого байта из данных, которые передаются в текущем сегменте. 196 | 197 | Если же требуется разделять данные в посылаемом стриме (то есть отделять один элемент данных от другого), то приложение должно позаботиться об этом само и вставлять в данные определенный delimiter, согласованный с другой стороной (например multipart/form-data). 198 | 199 | ### Установка соединения (Handshake) 200 | 201 | В протоколе TCP процедура установки соединения получила название **Three-Way Handshake**. Данная процедура проходит три шага: 202 | 1. Клиент посылает пакет SYN (сокр. Synchronize), сообщая этим о желании установки соединения 203 | 2. Сервер отвечает пакетом SYN-ACK (Synchronize-Acknowledge), если способен обработать запрос и принять новое соединение 204 | 3. Клиент подтверждает приём пакета SYN-ACK пакетом ACK. На этом процедура установки соединения завершается. 205 | 206 | #### SYN Flood 207 | 208 | Протокол TCP имеет потенциальную уязвимость, обусловленную тем, что нарушитель, устанавливая фальшивые IP-адреса отправителя, может послать серверу множество пакетов SYN. При получении пакета SYN сервер выделяет часть своих ресурсов для установки нового соединения. Обработка множества пакетов SYN рано или поздно затребует все ресурсы сервера и сделает невозможной обработку новых запросов. Такой вид атак называется [SYN flood](https://ru.wikipedia.org/wiki/SYN-%D1%84%D0%BB%D1%83%D0%B4). 209 | 210 | ### TCP Sliding window Acknowledgement system 211 | 212 | Почему нам вообще понадобилась надежность передачи данных и их упорядоченность? Потому что при передаче по сети может произойти много ошибок, сообщение может не дойти или дойти поврежденным, IP не гарантирует целостности или порядка сообщений. Именно поэтому нам понадобился такой протокол как TCP, чтобы избавить нас от необходимости следить за всем этим. Все, что нам надо сделать для знания того, что данные придут как нужно - это писать в открытый TCP сокет. 213 | 214 | Итак, с какими проблемами справляется TCP: 215 | - Overlapping Transmissions - разрешение ситуации когда посылается множество запросов и ответов в быстром режиме 216 | - Acknowledgment of Multiple Segments - когда одним запросом со стороны receiver-а подтверждается сразу несколько пакетов, которые послал sender 217 | - Fluctuating Window Sizes For Flow Control - контроль размера окна для Back Pressure 218 | - Lost Transmissions - восстановление потерянных пакетов 219 | - Congestion Handling and Avoidance - контроль и избежание congestion (перегрузка сети). 220 | 221 | Давайте поговорим о том, как TCP делает свою магию. Все скрыто в *TCP Sliding window Acknowledgement system*. 222 | 223 | **TCP Sliding window Acknowledgement system** - это усовершенствованная версия *PAR* (Positive Acknowledgment with Retransmission). **Par**, в свою очередь, это система которая ожидает подтверждения получения посланного сообщения, причем следующее сообщение не может послаться, пока не придет подтверждение, то есть работа синхронная. Если подтверждения не приходит в течение какого-то таймаута, то сообщение посылается снова. Очевидно, такая система является медленной. TCP базируется на ней, но сильно модифицирует. 224 | 225 | ### Flow Control 226 | 227 | Flow Control гарантирует, что sender не перегрузит receiver посылая пакеты быстрее чем receiver может их читать. Обычно это называется Back-Pressure в распределенных системах. 228 | 229 | Чтобы контролировать количество данных, которые может послать sender, receiver сообщает о своем значении *Receive Window (Send Window, Window)*, то есть свободном месте в буфере. 230 | 231 | ![Receive Windows](assets/rwnd.png) 232 | 233 | Каждый раз когда receiver получает пакет данных, он должен отправить `ACK` сообщение sender-у, подтверждая получение пакета, а вместе в ACK сообщении он также должен отправить оставшееся свободное место в буфере. 234 | 235 | Здесь вступает в дело такое понятие как **The sliding Window**. 236 | 237 | Итак, допустим что мы установили соединения между сокетами A (sender) и B (receiver). Нам необходимо передать 150000 байт по сети. B сообщает, что его Receive Window равен 45000 байт. Тогда это означает, что A может отправить без опаски перегрузить B 100 пакетов по 1500 байтов каждый. Если, допустим, B посылает `ack` для первых 10 пакетов и Receive Window все еще равен 45000 (что означает, что приложение на стороне B уже прочитало данные из буфера). Тогда A может отправить еще 10 пакетов, дополняя количество пакетов, находящихся *"в полете"* (то есть отправленных, но еще не были подтверждены), обратно до 30 (то есть лимита, определенного значением Receive Window). 238 | 239 | ![sliding window](assets/sliding_window.png) 240 | (пример sliding window - как только пакет 3 будет подтвержден (acked), мы можем сдвинуться вправо и отправить пакет 8) 241 | 242 | Теперь, допустим, клиент на стороне B начинает читать медленнее. Тогда если еще следующие 10 пакетов были подтверждены (и в полете находятся 20 пакетов, то есть 30000 байт), но receive window в `ack` ответе равен 30000 байт, то мы не можем отправить еще пакеты, так как в полете находятся столько же байт сколько B может принять. 243 | 244 | **А что же происходит в таком случае с приложением, которое пишет в TCP output socket (то есть пишет в send buffer)?** Если сокет блокирующий, то при заполнении send buffer (что как раз происходит, если receiver не мог читать быстрее, чем мы писали), приложение тоже блокируется, пока не освободится место в сокете. Тогда мы можем использовать non-blocking I/O, мультиплексирование, или async I/O. Тут же отмечу, что и читающее приложение может заблокироваться, если sender пишет медленнее, чем received может читать - если используются блокирующие сокеты (то есть recv() блокируется, ожидая данных в receive buffer). 245 | 246 | Здесь существует проблема, если B сообщает что receive windows равен 0, но не посылает больше ack сообщений (или ack теряется), A никогда не узнает может ли он посылать данные снова. То есть мы имеем deadlock ситуацию. 247 | 248 | Чтобы решить эту проблему, когда A встречает receive window равное 0 он запускает *Persist Timer*, который периодически посылает маленький пакет receiver-у (обычно называется WidowProbe), поэтому имеет возможность встретить receive window не равное 0 и продолжить посылать сообщения. 249 | 250 | ![Widow probe](assets/window_probe.png) 251 | 252 | ### Порядок и надежность данных, Retransmission, Multiple Segments Acknowledgment 253 | 254 | **А как же соблюдаются порядок и надежность данных?** 255 | 256 | Обычно при использовании **PAR** отправитель посылает сообщение и блокируется, ожидая Acknowledgment в ответ. Однако это неэффективно, так как блокируясь, мы не можем послать еще данных. TCP улучшает стандартный алгоритм PAR и использует для посланных пакетов так называемое *Sequence Number*, которое позволяет идентифицировать сегменты данных и знать, к какому сегменту данных относится `ack` ответ, в котором указывается Acknowledgment Number. Более того, TCP может использовать всего 1 ACK ответ сразу для нескольких посланных пакетов. Так, если были посланы байты 32-34, 35-36, 37-41 и 42-45, то при получении ACK с *Acknowledgment Number* = 37 мы знаем, что байты 32-36 успешно переданы. Однако, здесь есть нюанс: даже если байты 42-45 пришли, но 37-41 - нет, то подтверждения для 45 байта не придет, так как это означало бы, что байты 37-41 тоже пришли, чего на самом деле не было. 257 | 258 | Поэтому, как и любая PAR система, TCP для восстановления потерянных пакетов (Lost Transmission) имеет механизм ретрансляции (Retransmission) - после каждой отправки пакета sender запускает Retransmission Timer для этого пакета, который при истечении времени, если подтверждение не пришло, пересылает этот пакет данных. Тогда по истечении некоторого времени байты 37-41 отправятся снова. 259 | 260 | Подводя итог, TCP хранит в сегменте данных следующие важные хэдеры: 261 | - Sequence Number: определяет порядковый номер первого байта из данных, которые передаются с стороны sender'а 262 | - Acknowledgment Number: определяет порядковый номер первого байта из данных, которые ожидается для приема на стороне receiver'а, что также означает что все байты меньше этого значения уже были получены. Например, если двумя запросами отправлены пакеты с seq = 1 с размером сегмента 80 байт и seq = 81 с размером сегмента 120 байт, то при получении ответа ack с Acknowledgment Number=201 мы знаем, что 200 байт успешно переданы и можем отправить еще 200 байт. 263 | - Window: размер Receive Window устройства, отправляющего этот сегмент (со стороны receiver - это размер окна receiver-а) 264 | 265 | **Пример общения хостов по TCP:** 266 | 267 | ![TCP Transaction Example With Retransmission](assets/tcpswretrans.png) 268 | 269 | Что здесь происходит: 270 | 1. Сервер и клиент установили соединение и клиент сообщил о своем размере окна в 560 байт 271 | 2. Сервер посылает 4 сегмента данных с Seq Num = 1, Seq Num = 81, Seq Num = 201 общим размером 360. Однако 3 сегмент теряется при передаче по сети. При этом сервер отслеживает, сколько байт он уже отправил и также контролирует на своей стороне, сколько он может отправить еще (действие Flow Control) 272 | 3. Клиент принимает 2 первых сегмента, сохраняет в буфер и сдвигает свое окно вперед, тем самым он снова может принять 560 байт. После сохранения он отсылает `ACK` с Acknowledgment Number = 201, обозначая что первые 200 байт успешно приняты 273 | 4. Сервер посылает еще 4 сегмент с Seq Num = 361. Общий размер теперь равен 500 байт, поэтому сервер может отправить еще 60 байт 274 | 5. Клиент принимает 4 сегмент и кладет его в буфер. Однако, клиент кладет его не за 2 сегментом, а располагает его, начиная с Seq Num, указанного в сегменте, то есть начиная с 361 байта. Мы видим, что место которое должно было быть занято 3 сегментом пустует, так как пакет потерялся. Клиент не может отправить `ACK`, так как отсутствует 3 сегмент 275 | 6. Сервер принимает `ACK` ответ от клиента для первых 200 байт и смещает свое окно вперед, таким образом сервер может отправить теперь еще 260 байт 276 | 7. Исходит время таймаута таймера ретрансляции (Retransmission Timer) для 3 сегмента, и сервер посылает снова 3 сегмент с Seq Num = 201 277 | 8. Клиент принимает этот сегмент, располагает его в буфере между 2 и 4 сегментами (т.е. начиная с 201 байта) и отсылает `ACK` с Ack Num = 501, обозначая что все 4 сегмента успешно приняты 278 | 9. Сервер принимает `ACK` ответ от клиента и смещает свое окно вперед. Теперь он снова может отправить 560 байт, а клиент принять 560 байт 279 | 10. Общение продолжается... 280 | 281 | ### Congestion 282 | 283 | *Congestion* - это не то же самое, что и Back Pressure (FLow Control в TCP). Flow Control контролирует периодичность (rate) с которой sender может посылать сообщения. Однако, FLow Control контролирует только то, что происходит с устройствами на каждой из сторон TCP соединения, но не контролирует то, что происходит в устройствах *между* ними. Да, следуя абстракции, мы всего лишь соединены "напрямую" с хостом и это не наша забота, так как Transport Layer знает только о другом хосте и ничего о нижних уровнях и маршрутизаторах/кабелях под океаном. 284 | На практике же, то что происходит на Сетевом уровне - очень важно. Если межсетевое взаимодействие (internetwork) становится слишком загруженной, то скорость, с которой передаются TCP пакеты, может снизиться и пакеты могут даже начать теряться. Это и называется **congestion**. TCP для решения этой задачи имеет в себе алгоритм ![exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff) для того, чтобы подбирать оптимальное время для повторной посылки сообщения. 285 | 286 | --- 287 | 288 | ## Адресация пакетов 289 | 290 | Сетевые пакеты могут достичь пункта назначения только при наличии адреса доставки. В модели TCP/IP используется несколько уровней адресации: 291 | - *Link layer:* Адреса MAC (Media Access Control) для использования в сетевом оборудовании 292 | - *Internet Layer:* IP адреса для использования в программном обеспечении 293 | 294 | ### \[Link layer\] MAC 295 | 296 | **MAC** - это протокол для передачи пакетов на уровне сетевого оборудования. 297 | 298 | #### MAC Address 299 | 300 | На канальном уровне - самом нижнем уровне адресации, где играют роль аппаратные средства - каждый сетевой интерфейс компьютера имеет **MAC адрес**, который отличает его от других компьютеров в сети. Например, Ethernet устройствам в процессе изготовления назначаются уникальные шестибайтовые аппаратные адреса. Эти адреса традиционно записываются в виде ряда двух шестнадцатеричных чисел, разделенных двоеточиями, например 00:50:8D:9A:3B:DF. 301 | В Ethernet-адресе первые 3 байта определяют изготовителя устройства, а последние три - выступают в качестве уникального серийного номера, назначаемого изготовителем. По первым 3 байтам можно выяснить марку устройства, поиска его в таблице идентификаторов изготовителей. Она расположена по адресу [http://www.iana.org/assignments/ethernet-numbers/ethernet-numbers.xhtml](http://www.iana.org/assignments/ethernet-numbers/ethernet-numbers.xhtml) 302 | 303 | --- 304 | 305 | ### \[Internet Layer\] IP 306 | 307 | **Internet Protocol** - это протокол для передачи датаграмм на уровне хостов в сети. 308 | 309 | #### IP Address 310 | 311 | **Internet Protocol address (IP address)** - это уникальный сетевой адрес устройства, подключенного к сети. IP адрес служит для двух целей: идентификация хоста (а точнее, сетевого интерфейса) и расположение хоста в сети. 312 | 313 | #### Версии IP 314 | 315 | IPv4 (4 версия Internet Protocol) определяет IP адрес как число длиной 32 бита, а IPv6 как 128 бит. IP адрес записывается в виде 4-х чисел (октетов), разделенных точкой. Например: 172.16.254.1. Тот же адрес, но в бинарной форме: 10101100.00010000.11111110.00000001 316 | 317 | Дальше мы будем говорить про IP-адрес в IPv4. 318 | 319 | --- 320 | 321 | ## IP: Подсети (Subnetworks) 322 | 323 | IP-адреса могут быть логически разделены на подсети. Разделение на подсети дает нам возможность создать из одной сети с огромным количеством адресов множество сетей с меньшим количеством адресов. Общее количество адресов остается таким же, однако таким образом мы можем более тонко выдавать пачки адресов сетям, где не требуется большое количество адресов. 324 | 325 | После разделения IP адрес должен читаться как 2 части: *сеть* (сетевой префикс, network prefix) в битах более высокого порядка и *узел*, то есть идентификатор хоста в этой сети в оставшихся битах. Для разделения используется маска подсети. Маска подсети определяет, какая часть IP-адреса относится к адресу сети, а какая - к адресу самого узла в этой сети. 326 | 327 | В маске всегда сначала идут единицы, а затем - нули. Маска может записываться как 4 числа (октета), разделенных точками, например 255.255.255.0, а может записываться как суффикс IP адреса (CIDR Notation). Та же маска записывалась бы в CIDR как /24, то есть первые 24 бита определяют сеть. 328 | 329 | Адрес сети (сетевой префикс) можно вычислить как адрес сети используя побитовую операцию AND между IP-адресом и маской. Адрес же узла можно вычислить как побитовую операцию AND между IP-адресом и инвертированной маской подсети. 330 | 331 | ### Анализ подсети 332 | 333 | При знании IP адреса и маски подсети мы можем получить много полезной информации. Например, для адреса 172.16.254.1 и маски подсети /26: 334 | - IP-адрес - 10101100.00010000.11111110.00000001 - 172.16.254.1 335 | - Маска подсети - 11111111.11111111.11111111.11000000 - 255.255.255.192 336 | - Адрес сети - 10101100.00010000.11111110.00000000 - 172.16.254.0 - данный адрес не доступен для назначения хостам 337 | - Адрес узла - 00000000.00000000.00000000.00000001 - 0.0.0.1 338 | - Широковещательный адрес (Broadcast) - 172.16.254.63 - данный адрес не доступен для назначения хостам 339 | - Первый доступный для назначения адрес в сети - 172.16.254.1 340 | - Последний доступный для назначения адрес в сети - 172.16.254.62 341 | - Всего хостов в сети - 64 (включая broadcast адрес и адрес сети) 342 | 343 | ### Пример разделения на подсети 344 | 345 | Пусть нам выдана пачка адресов 192.168.5.0/24. Тогда мы можем разделить эту большую сеть на 4 сети /26. Делается это путем увеличения маски подсети на 2 бита (2^2 = 4). 346 | 347 | У нас есть маска подсети /24, то есть: 348 | `11111111.11111111.11111111.00000000`. В такой сети мы имеем 2^8 (256) узлов. Теперь, при увеличении маски подсети на 2 бита, у нас уменьшается оставшееся для хостов количество битов на 2 бита, то есть в сети /26 получается 64 свободных адреса, однако самих сетей стало ровно 4 вместо 1. 349 | 350 | Если у нас была сеть 192.168.5.0/24 с диапазоном адресов 192.168.5.0-192.168.5.255, то теперь получились следующие 4 подсети c 64 узлами в себе: 351 | 352 | Адрес сети - бинарный адрес сети - broadcast адрес (последний адрес в сети): 353 | - 192.168.5.0/26 - 11000000.10101000.00000101.00000000 - 192.168.5.63 354 | - 192.168.5.64/26 - 11000000.10101000.00000101.01000000 - 192.168.5.127 355 | - 192.168.5.128/26 - 11000000.10101000.00000101.10000000 - 192.168.5.191 356 | - 192.168.5.192/26 - 11000000.10101000.00000101.11000000 - 192.168.5.255 357 | 358 | --- 359 | 360 | ## Публичные и приватные IP адреса 361 | 362 | IP адреса бывают публичными и частными. Публичный IP адрес - это IP адрес, используемый для выхода в интернет. [Частный IP адрес](https://en.wikipedia.org/wiki/Private_network) (private) - это адрес, который используется исключительно в локальной сети и не маршрутизируется в интернете. 363 | 364 | Любой сайт в интернете должен использовать публичный IP адрес, чтобы к нему можно было подключиться. Публичные IP адреса выдаются интернет-провайдерами. Частный же IP адрес мы можем назначить любому локальному компьютеру в локальной сети сами, главное чтобы IP адрес был уникальным для этой сети. 365 | 366 | Частные IP адреса зафиксированы: 367 | - Local addresses: 368 | - Class A Private Range: 10.0.0.0/8 - диапазон адресов 10.0.0.0 - 10.255.255.255 369 | - Class B Private Range: 172.16.0.0/12 - диапазон адресов 172.16.0.0 - 172.31.255.255 370 | - Class C Private Range: 192.168.0.0/16 - диапазон адресов 192.168.0.0 - 192.168.255.255 371 | - Link-local addresses: 169.254.0.0/16 - диапазон адресов 169.254.0.0 - 169.254.255.255 372 | - Loopback interface: 127.0.0.0/8 - диапазон адресов 127.0.0.0 - 127.255.255.255 373 | 374 | ### Loopback Interface 375 | 376 | На каждом ОСи существует специальный сетевой интерфейс, предназначенный для коммуникации внутри хоста. Пакеты, посылаемый на данный интерфейс, выглядят как настоящие, но не проходят через сетевую карту и не уходят в сеть, а попадают сразу во входящую очередь пакетов текущего хоста. Специальное зарезервированное доменное имя для этого - localhost. Для сети, состоящей из одного компьютера, используется всего один адрес - 127.0.0.1, который как раз и устанавливается на специальный сетевой интерфейс под названием loopback interface. 377 | 378 | --- 379 | 380 | ## Маршрутизация 381 | 382 | Для передачи IP пакетов на хосты мы должны знать, куда отправлять пакет. Ранее уже говорилось, что IP-адреса выступают и в целях определения пути, по которому следует передать пакет. 383 | 384 | Для определения пути используется *Routing Table*. 385 | 386 | **Routing Table** - это специальная таблица в ядре ОСи, которая содержит инструкции по передаче IP пакетов. В каждой строчке таблицы имеется собственно сам адрес сети, маска сети, название сетевого интерфейса и Gateway адрес (адрес шлюза) - адрес, на который следует передать пакет, чтобы он попал в сетевой интерфейс. 387 | 388 | **Шлюз** - это коммутатор, который способен передать пакет в другую сеть. Его IP-адрес - это обычно первый адрес из подсети, в которой находится отправитель, хотя это и не обязательно. Например, если отправитель находится в сети 192.168.8.0, то адрес шлюза - 192.168.8.1. Важное уточнение: в стандартный шлюз пакеты попадают только если адрес назначения пакета - другая сеть. Пакеты, предназначенные хостам той же подсети, в которой находится отправитель, передаются напрямую, но не попадают в шлюз. 389 | 390 | Например, пусть таблица маршрутизации содержит следующую запись: 391 | - Адрес сети: 172.16.129.0, маска: 255.255.255.0 (/24), адрес шлюза: 172.16.129.1. Диапазон адресов, которое покрывает данное правило - 172.16.129.0-172.16.129.255 392 | - Адрес сети: 172.16.0.0, маска: 255.255.0.0 (/16), адрес шлюза: 0.0.0.0. Диапазон адресов - 172.16.0.1-172.16.255.255 393 | - Адрес сети: default, маска: 0.0.0.0, адрес шлюза: 192.168.8.1 - стандартный шлюз. Все пакеты, которые не попадают в правила выше, идут сюда 394 | 395 | При получении адреса назначения мы по очереди накладываем маску каждой записи на адрес назначения. Если при наложении маски получился тот же адрес сети, что и указан в таблице, то используется данная запись и пакет посылается на шлюз, установленный в записи. Причем накладывается сначала как можно более длинная маска, так как для одной большой сети могут существовать отдельные правила для подсетей, которые перекрывают правила. Например, в таблице выше первое правило перекрывает второе правило, если адрес назначения попадает в диапазон адресов первого правила. 396 | 397 | При ручном добавлении записи в таблицу маршрутизации маска должна полностью покрывать все биты, установленные в единицу в адресе сети. Это необходимо потому, что при получении адреса назначения мы должны наложить маску на адрес назначения и посмотреть получившийся адрес сети. Если маска не будет покрывать биты, установленные в адресе сети в единицу, то такой адрес сети при наложении никогда не вычислится (при битовой операции И если хотя бы один бит установлен в 0, то результат = 0. Поэтому, даже если в адресе назначения присутствует нужная единица, а в маске нет, то результатом будет 0). 398 | 399 | Например, мы получаем адрес назначения 172.16.129.54. Начинаем накладывать самую длинную маску - это 255.255.255.0. Результатом является адрес сети 172.16.129.0. Шлюз для нее - 172.16.129.1, пакет идет туда. 400 | Теперь пусть мы получили адрес 172.16.45.32. Накладываем самую длинную маску - результатом является адрес сети 172.16.45.0, который не попадает в первое правило, однако попадает во второе правило, пакет идет в стандартный шлюз 0.0.0.0. 401 | Теперь пусть мы получаем адрес 192.168.0.1 - он не попадает ни в одну подсеть, поэтому идет на стандартный шлюз. 402 | 403 | Посмотреть таблицу маршрутизации в Linux мы можем посмотреть с помощью команды `netstat -rn`. Вот пример вывода программы: 404 | 405 | ```text 406 | % netstat -rn 407 | Kernel IP routing table 408 | Destination Genmask Gateway Fl MSS Iface 409 | 132.236.227.0 255.255.255.0 132.236.227.93 U 1500 eth0 410 | default 0.0.0.0 132.236.227.1 UG 1500 eth0 411 | 132.236.212.0 255.255.255.192 132.236.212.1 U 1500 eth1 412 | 132.236.220.64 255.255.255.192 132.236.212.6 UG 1500 eth1 413 | 127.0.0.1 255.255.255.255 127.0.0.1 U 3584 lo 414 | ``` 415 | 416 | В рассматриваемой системе есть два сетевых интерфейса: 132.236.227.93 (eth0) — в сети 132.236.227.0/24 и 132.236.212.1 (eth1) - в сети 132.236.212.0/26. 417 | 418 | Поле destination содержит адрес сети. В поле gateway отображается адрес локального сетевого интерфейса или соседнего узла; в ядре системы Linux для вызова шлюза, установленного по умолчанию, в поле gateway может быть записан адрес 0.0.0.0. Например, четвертый маршрут указывает, что для достижения сети 132.236.220.64/26 пакеты следует посылать в шлюз 132.236.212.6 через интерфейс eth1. Вторая запись содержит описание стандартного маршрута. Пакеты, не адресованные явно ни в одну из трех указанных сетей (или самому компьютеру), будут направлены в стандартный шлюз 132.236.227.1. 419 | 420 | Компьютеры могут посылать пакеты только тем шлюзам, которые физически подключены к той же сети. Локальные компьютеры могут перемещать пакеты только на один шаг в направлении пункта назначения, поэтому в него бессмысленно включать информацию о шлюзах, не являющихся смежными в таблице локальной маршрутизации. Каждый шлюз, через который проходит пакет, принимает следующее решение о его перемещении, анализируя собственную таблицу локальной маршрутизации. 421 | 422 | Вести таблицы маршрутизации можно статически, динамически или комбинированным способом. Статический маршрут задается в явном виде с помощью команды route. Он должен оставаться в таблице маршрутизации в течение всего времени работы системы. Во многих случаях такие маршруты задаются на этапе начальной загрузки с помощью одного из сценариев запуска системы. Например, команды `route add -net 132.236.220.64 netmask 255.255.255.192 gw 132.236.212.6 eth1` и `route add default gw 132.236.227.1 eth0` добавляют, соответственно, четвертый и второй маршруты из числа тех, что отображаются выше командой `netstat -rn` (первый и третий маршруты добавляются командой ifconfig при конфигурировании интерфейсов eth0 и eth1). 423 | 424 | Последний маршрут также добавляется на этапе начальной загрузки. Он определяет псевдоустройство, называемое интерфейсом обратной связи (loopback interface). Это устройство препятствует пакетам, которые компьютер посылает сам себе, выходить в сеть. Вместо этого они напрямую переносятся из выходной сетевой очереди ядра во входную очередь. 425 | 426 | Большинство компьютеров локальной сети имеет единственный выход во внешний мир, поэтому маршрутизация осуществляется очень просто: достаточно на этапе начальной загрузки добавить стандартный маршрут. Компьютер может получить стандартный маршрут вместе со своим IP-адресом у сервера DHCP. 427 | 428 | --- 429 | 430 | ## Ресурсы и источники 431 | 432 | - [http://www.tcpipguide.com/index.htm](http://www.tcpipguide.com/index.htm) 433 | - [https://www.brianstorti.com/tcp-flow-control/](https://www.brianstorti.com/tcp-flow-control/) 434 | - [Книга Unix и Linux. Руководство системного администратора](https://www.labirint.ru/books/749458/) 435 | --------------------------------------------------------------------------------