Поскольку я задал этот вопрос, я узнал больше об этой теме, поэтому я постараюсь ответить на него сам.
Самый простой способ изобразить стек протоколов - это письмо, завернутое в серию конвертов. Каждый конверт играет свою роль в получении письма получателю, и конверты добавляются и удаляются по мере необходимости.
Уровень приложений
Само письмо является запросом прикладного уровня. Например, вы набрали «StackOverflow.com» в своем браузере и нажали Enter. Ваш браузер должен запросить у сервера StackOverflow домашнюю страницу. Поэтому он пишет письмо, в котором говорится: «Уважаемый StackOverflow, не могли бы вы выслать мне свою домашнюю страницу?»
Если автором письма является ваш браузер, получателем письма является программа веб-сервера, работающая в StackOverflow. Браузер хочет, чтобы веб-сервер «ответил» ответом в виде веб-страницы. И браузер, и сервер являются приложениями - программами, работающими на определенных компьютерах.
Поскольку браузеры говорят по HTTP, именно это он и использует для выполнения запроса: в письме говорится что-то вроде «GET * 1014». Браузер также записывает любую информацию о cookie, полученную от StackOverflow в прошлый раз («помните меня? сказал мне, что мой логин был «X») и добавляет некоторую различную помеченную информацию под названием «заголовки» (такие вещи, как «Я Firefox» и «Я могу принять HTML или текст» и «все в порядке, если вы сжимаете содержимое с помощью gzip») "). Вся эта информация поможет серверу узнать, как персонализировать или настроить свой ответ.
На этом этапе браузер в основном готов. Он передает это письмо операционной системе и говорит: «Не могли бы вы прислать это мне?» ОС говорит: «Конечно». Затем он выполняет некоторую работу по подключению к StackOverflow (подробнее об этом через минуту), а затем сообщает браузеру: «Я работаю над этим. Кстати, вот небольшой почтовый ящик, который я сделал для вас, который называется сокетом. Когда Я слышу ответ от StackOverflow, я положу туда его письмо, и вы сможете прочитать его, как файл. " Затем браузер с радостью ждет ответа.
Уровень IP
Чтобы отправить запрос из браузера в StackOverflow, операционная система должна сделать несколько вещей.
Во-первых, он должен найти адрес для StackOverflow.com, в частности, IP-адрес. Это делается с помощью DNS (я не буду вдаваться в подробности). Как только он узнает IP-адрес, он будет знать, как обернуть запрос в один из «конвертов», называемых IP-уровнем.
Зачем нам нужен уровень IP? Ну, когда-то, мы не сделали.
Зачем нам нужен IP
Вы когда-нибудь видели старый фильм, где кто-то делает телефонный звонок, прося оператора подключить их? Оператор физически подключал бы провод от дома № 1 к проводу для дома № 2. До изобретения стека протоколов подключение компьютеров было очень похоже на этот телефонный звонок: вам требовался выделенный провод от точки к точке.
Так, например, если бы компьютерные ученые в Стэнфорде хотели обмениваться данными с данными в Гарварде, они заплатили бы кучу денег, чтобы арендовать выделенный провод между двумя местами («выделенная линия»). Любые данные, которые попали в один конец, надежно вышли в другом конце. Однако это было очень дорого: представьте, что вы платите за отдельную линию для каждого места, к которому хотите подключиться!
Люди поняли, что это не увеличится. Нам нужен был способ создать сеть, которая была бы общей для всех пользователей, например гигантский паутина проводов, раскиданных по всей карте. Таким образом, каждому пользователю потребуется только одно соединение с сетью, и он может связаться с любым другим пользователем через него.
Но это представляло проблему. Если бы все коммуникации проходили по одной линии, как бы данные попали в нужное место? Представьте себе кучу писем, сброшенных на конвейер. Очевидно, что каждое письмо должно быть адресовано кому-то, иначе оно не может быть доставлено.
Это основная идея IP: каждая машина должна иметь IP-адрес, который однозначно ее идентифицирует. Сообщения помещаются в IP-пакеты, которые похожи на конверты с адресами и обратными адресами.
Итак, когда ОС проверила IP-адрес для Stackoverflow.com, она помещает HTTP-запрос в IP-конверт. Если это «длинное письмо», слишком большое для одного конверта, ОС разрезает его на несколько частей и помещает в несколько IP-конвертов. Каждый конверт говорит что-то вроде «FROM: (ваш IP-адрес); TO: (IP-адрес сервера». Как и HTTP-запрос, IP-пакет содержит некоторую другую информацию заголовка, которую мы не будем здесь рассматривать, но основные идея просто "до" и "от".
Итак, на данный момент письмо готово к отправке, верно?
Грязность IP
Не совсем. Это письмо может легко потеряться! Видите, с IP у нас больше нет выделенной линии с места на место. Если бы мы это сделали, мы были бы уверены, что наши письма были доставлены: до тех пор, пока линия не будет разорвана, все будет проходить.
Но с IP все пакеты сбрасываются на конвейерные ленты и переносятся. Пояса приводят к небольшим сортировочным станциям, называемым «маршрутизаторами». Если вы представляете маршрутизаторы как физические почтовые центры, вы можете представить их, скажем, в Нью-Йорке.
"Вот письмо, направляющееся в Мехико. Я не знаю точно, как туда добраться, но станция в Хьюстоне должна быть в состоянии приблизить его, поэтому я отправлю его туда. Ах, вот письмо, которое еду в Атланту. Я отправлю это Шарлотте, они должны быть в состоянии переслать это на шаг ближе. "
Обычно эта система работает нормально, но она не так надежна, как собственная выделенная линия. В пути может произойти почти все: конвейерная лента может сломаться или загореться, и все на ней может быть потеряно. Или можно на какое-то время застрять, чтобы его пакеты были доставлены очень поздно.
Кроме того, поскольку эти конвейерные ленты и станции используются всеми, никто не обращается с письмами специально. Так что же произойдет, если маршрутизатор получит больше писем, чем может обработать? Какое-то время он может складывать их в угол (возможно, в ОЗУ), но в конце концов ему не хватает места.
То, что он делает, может показаться шокирующим: он начинает их выбрасывать.
Да. Вот и все. Вы можете подумать, что, по крайней мере, было бы достаточно любезно отправить вам записку со словами: «Извините, мы не смогли доставить ваше письмо». Но это не так. Если вы думаете об этом, если маршрутизатор перегружен, это, вероятно, потому, что на линиях уже слишком много трафика. Добавление извинений только усугубит проблему. Таким образом, он выбрасывает ваш пакет и не говорит никому.
Очевидно, это проблема для нашего HTTP-запроса. Нам это нужно, чтобы добраться туда, и нам нужен ответ, чтобы получить надежный ответ.
Чтобы убедиться, что он туда попадет, нам нужна какая-то услуга «подтверждения доставки». Для этого мы обернем еще один конверт вокруг нашего HTTP-запроса, прежде чем помещать его в IP-пакеты. Этот слой называется TCP.
TCP
TCP означает «протокол управления передачей». Он существует для контроля того, что в противном случае было бы грязным, подверженным ошибкам процессом доставки.
Как и предполагалось ранее, TCP позволяет нам добавить «подтверждение доставки» в эту грязную систему доставки. Прежде чем мы обернем наш HTTP-запрос в IP-пакеты, мы сначала поместим его в TCP-пакеты. Каждому из них присваивается номер: пакет 1 из 5, 2 из 5 и т. Д. (Схема нумерации на самом деле является более сложной и учитывает байты, а не пакеты, но давайте пока проигнорируем это.)
Основная идея TCP заключается в следующем:
- Во-первых, клиент и сервер - в данном случае ваша операционная система и операционная система сервера StackOverflow - выполняют «рукопожатие» для установления «соединения».Оба слова нуждаются в кавычках, потому что «рукопожатие» - это на самом деле несколько сообщений взад и вперед, доказывающих, что пакеты могут успешно доставляться туда и обратно, а «соединение» - это не более чем каждая сторона, решающая, что они будут отслеживать пакетымежду ними течет.
- Далее они отправляют пакеты туда и обратно;клиент может запрашивать веб-страницу, а сервер может отправлять ее обратно (столько пакетов, сколько требуется).
- Когда одна сторона получает пакеты, она отправляет обратно сообщения с подтверждением, говоря «пока я получил ваши пакеты до пакета 100» и так далее.Если одна сторона отправляет пакеты и некоторое время не слышит подтверждения, она будет считать, что они были потеряны, и повторно отправит их.
(Получение подтверждений, когда вещи приходят на другой конец, лучше, чемполучение отчетов об ошибках, когда маршрутизатор отбрасывает вещи по пути по нескольким причинам. Одна из них заключается в том, что подтверждения возвращаются через работающее соединение, в то время как ошибки приводят к засорению нерабочего соединения. Во-вторых, нам не нужно доверятьпромежуточные маршрутизаторы делают правильные вещи: клиент и сервер - это те, кто больше всего заботится об этом конкретном разговоре, поэтому именно они отвечают за то, чтобы убедиться, что он работает.)
Кроме того, чтобы убедиться, чтовсе данные попадают на другой конец, TCP также проверяет, что полученные данные возвращаются в правильном порядке перед передачей их в стек, в случае, если более ранние пакеты были повторно отправлены и доставлены позже, или пакеты в середине заняли более длинный маршрутили что-то еще.
Вот и все -Такое подтверждение доставки делает ненадежную IP-сеть надежной.
Почему она не была встроена в IP?
UDP
Ну, подтверждение имеет недостаток: оно замедляет работу.Если что-то пропущено, это нужно повторить.В некоторых случаях это было бы пустой тратой времени, потому что вам действительно нужно 1089 * соединение в режиме реального времени.Например, если вы разговариваете по телефону через IP или играете в игру в реальном времени через Интернет, вы хотите знать, что происходит прямо сейчас , даже если это означает, что вы пропустилинемного из того, что произошло секунду назад.Если вы перестанете повторять что-то, вы потеряете синхронизацию со всеми остальными.В подобных случаях вы можете использовать двоюродного брата TCP, называемого UDP, который не пересылает потерянные пакеты.UDP означает «протокол пользовательских дейтаграмм», но многие считают его «ненадежным протоколом данных».Это не оскорбление;иногда надежность менее важна, чем постоянный ток.
Поскольку оба они являются допустимыми вариантами использования, имеет смысл, что протокол IP остается нейтральным в вопросе надежности;те, кто его использует, могут выбирать, добавлять ли надежность или нет.
Как TCP, так и UDP добавляют к запросу еще одну важную информацию: номер порта.
номера портов
Помните, наш первоначальный запрос поступает из браузера и направляется на программу веб-сервера.Но у протокола IP есть только адреса, которые указывают компьютеры, а не приложения, работающие на них.На машине с веб-сервером StackOverflow могут также присутствовать другие серверные программы, которые прослушивают запросы: сервер базы данных, FTP-сервер и т. Д. Когда этот компьютер получает запрос, как он узнает, какая программа должна его обработать?
Он будет знать, потому что в запросе TCP указан номер порта.Это просто число, ничего особенного, но условно, что определенные числа интерпретируются как определенные вещи.Например, использование номера порта 80 является обычным способом сказать «это запрос к веб-серверу».Тогда операционная система сервера будет знать, что передать этот запрос программе веб-сервера, а не, скажем, программе FTP-сервера.
Когда TCP-пакеты начнут потоковую передачу обратно на ваш компьютер, у них также будет номер порта, чтобы ваш компьютер знал, на какую программу дать ответ. Это число будет зависеть от сокета, который изначально был создан на вашем компьютере.
Подождите, что такое сокет?
Головки
Помните ранее, когда браузер просил ОС отправить запрос? ОС заявила, что создаст «почтовый ящик» для любого полученного ответа. Этот контейнер называется сокетом.
Вы можете думать о сокете, как о файле. Файл - это интерфейс, который предоставляет ОС. Там написано: «Вы можете читать и записывать данные здесь, а я позабочусь о том, как на самом деле сохранить их на жестком диске, USB-накопителе или чем-то еще». То, что уникально идентифицирует файл, - это сочетание пути и имени файла. Другими словами, вы можете иметь только один файл, расположенный в той же папке с тем же именем.
Аналогично, сокет - это интерфейс, который предоставляет ОС. Там написано: «Вы можете писать запросы здесь и читать ответы». То, что однозначно идентифицирует сокет, - это комбинация четырех вещей:
- IP-адрес назначения
- Порт назначения
- IP-адрес источника
- Порт источника
Таким образом, в системе может быть только один сокет с одинаковой комбинацией всех этих. Обратите внимание, что вы можете легко открыть несколько сокетов для одного и того же IP-адреса и порта назначения, скажем, веб-сервера StackOverflow, если они имеют разные исходные порты. Операционная система гарантирует, что они это делают, выбирая произвольный порт источника для каждого запроса, поэтому у вас может быть несколько вкладок или несколько браузеров, запрашивающих один и тот же веб-сайт одновременно, без каких-либо затруднений; все возвращающиеся пакеты говорят, к какому порту на вашем компьютере они стремятся, что позволяет ОС знать «ах, этот пакет для вкладки 3 в Firefox» или что-то в этом роде.
Подводя итоги
Мы думали о протоколах как о серии конвертов, обернутых вокруг письма. В нашем примере это был HTTP-запрос, который был упакован в TCP, а затем в IP. IP-пакеты отправляются на правильный компьютер назначения. Этот компьютер удаляет IP-конверт и находит внутри TCP-пакет. Пакет TCP имеет номер порта, который позволяет операционной системе знать, в какой порт собирать его информацию. Он отвечает, что получил этот пакет, и помещает его содержимое (запрос HTTP) в правильный сокет для соответствующей программы, чтобы читать из. Когда эта программа записывает ответ в сокет, ОС отправляет его обратно запрашивающей стороне.
Итак, наш «стек»:
- HTTP-запрос («буква»). Это прикладной уровень.
- Завернут в пакеты TCP («конверты»). Это транспортный уровень.
- Завернут в IP-пакеты («конверты»). Это уровень IP.
Важно понимать, что этот стек полностью настраиваемый. Все эти "протоколы" являются просто стандартными способами работы. Вы можете поместить все, что вы хотите, в IP-пакет, если вы думаете, что принимающий компьютер будет знать, что с ним делать, и вы можете поместить все, что вы хотите, в TCP или UDP-пакет, если вы думаете, что принимающее приложение будет знать, что делать с это.
Вы можете даже поместить что-то еще в ваш HTTP-запрос. Вы могли бы сказать, что некоторые данные JSON - это «протокол обмена телефонными номерами», и если оба конца знают, что с ним делать, это нормально, и вы только что добавили протокол более высокого уровня.
Конечно, есть предел того, насколько «высоко» вы можете идти в стеке, то есть вы можете поместить меньший конверт в HTTP, и меньший в него и т. Д., Но в конечном итоге у вас не будет никакого комната, чтобы пойти меньше; у вас не будет битов для реального контента.
Но вы можете легко опуститься в стек; Вы можете обернуть больше "конвертов" вокруг существующих.
Другие уровни протокола
Однажды общим «конвертом» для обтекания IP является Ethernet. Например, когда ваш компьютер решает отправить IP-пакеты в Google, он упаковывает их, как мы уже описывали, но для отправки он передает их на вашу сетевую карту. Затем сетевая карта может обернуть IP-пакеты в пакеты Ethernet (или пакеты Token Ring, если у вас есть устаревшие настройки), направив их на ваш маршрутизатор и отправив их туда. Ваш маршрутизатор удаляет эти «конверты» Ethernet, проверяет IP-адрес, решает, кто является ближайшим маршрутизатором, оборачивает другой конверт Ethernet, адресованный этому маршрутизатору, и отправляет пакет.
Другие протоколы также могут быть упакованы. Возможно, два устройства подключены только по беспроводной связи, поэтому они оборачивают свои пакеты Ethernet в протокол Wi-Fi, Bluetooth или 4G. Возможно, ваши пакеты должны пересекать деревню без электричества, поэтому кто-то физически печатает пакеты на бумаге с пронумерованными страницами, проезжает по городу на велосипеде и сканирует их на другом компьютере в порядке номеров страниц. Вуаля! Протокол печати в OCR. Или, может быть, я не знаю, TCP через почтового голубя было бы лучше.
Заключение
Стек протоколов - прекрасное изобретение, и оно работает настолько хорошо, что мы обычно принимаем это как должное.
Это отличный пример абстрагирования функциональности: каждый слой выполняет свою работу и может полагаться на других, чтобы справиться с остальными.
- Уровень приложений касается только приложений, взаимодействующих друг с другом: «Firefox хочет общаться с веб-сервером на StackOverflow.com».
- Транспортный уровень касается только правильной доставки потока пакетов из одного приложения в другое: «все пакеты из порта 123 на машине 1 должны попасть в порт 80 на машине 2».
- Уровень IP * касается только маршрутизации отдельных пакетов: «этот пакет должен получить следующий IP-адрес».
- Канальный уровень касается только получения пакетов от одной путевой точки к следующей: «этот пакет Ethernet должен пройти от сетевой карты до маршрутизатора».
- Физический уровень связан только с передачей сигнала: «эти импульсы необходимо передавать по этому проводу».
(Хотя эти термины уровня заимствованы из OSI , OSI на самом деле являлся конкурирующим стандартом для TCP / IP и включал такие вещи, как «уровень сеанса» и «уровень представления», которые не поддерживает TCP / IP ». Использование OSI было задумано как более разумная и стандартизированная альтернатива небрежному хакерскому стеку TCP / IP, но пока он еще обсуждался, TCP / IP уже работал и получил широкое распространение.)
Поскольку слои можно смешивать и совмещать по мере необходимости, стек достаточно гибок, чтобы вместить практически любое использование, о котором мы только можем подумать, поэтому он, вероятно, будет существовать долгое время. И, надеюсь, теперь вы можете оценить это немного больше.