Компьютерные сети. 6-е изд. — страница 167 из 247

47. Рассчитайте произведение пропускной способности на задержку в следующих сетях:

а) T1 (1,5 Мбит/с);

б) Ethernet (10 Мбит/с);

в) Т3 (45 Мбит/с);

г) STS-3 (155 Мбит/с).

Предполагается, что RTT = 100 мс. Не забудьте, что в TCP-заголовке на размер окна отводится 16-разрядное поле. Как этот факт отразится на результатах вычислений?

48. Чему равно произведение пропускной способности на задержку для канала геостационарной спутниковой связи с пропускной способностью 50 Мбит/с? Если все пакеты имеют размер 1500 байт (включая накладные расходы), какого размера должно быть окно в пакетах?

49. По каким причинам тест пропускной способности сети доступа, выполняемый на стороне клиента, может не отражать реальную скорость канала доступа?

50. Рассмотрите TCP-заголовок (илл. 6.36). Каждый отправляемый TCP-сегмент включает четыре неиспользуемых бита. Как скажется на производительности удаление этих битов со смещением всех последующих полей на четыре бита влево?

51. Файловый сервер, код которого представлен на илл. 6.6, далек от совершенства. Неплохо было бы внести в него некоторые улучшения. Проделайте следующие изменения:

а) пусть у клиента появится третий аргумент, указывающий байтовый диапазон;

б) добавьте флаг –w в программу клиента, который позволил бы записывать файл на сервер.

52. Почти все сетевые протоколы должны уметь работать с сообщениями. Если вы помните, протоколы передают их путем добавления/отделения заголовков. Некоторые протоколы могут разбивать сообщение на несколько фрагментов, а потом восстанавливать его. Попробуйте разработать библио­теку управления сообщениями с поддержкой создания нового сообщения, добавления/отделения заголовка, разбиения одного сообщения на два, объединения двух сообщений в одно и сохранения копии сообщения. Минимизируйте, насколько это возможно, копирование данных из одного буфера в другой. Важно, чтобы эти операции работали только с указателями, не затрагивая данные в сообщении.

53. Разработайте и реализуйте систему сетевого общения (чат) для нескольких групп пользователей. Координатор чата располагается по общеизвестному сетевому адресу, использует для связи с клиентами UDP, настраивает чат-серверы перед каждой сессией общения и поддерживает каталог чат-сессий. На каждую сессию выделяется один обслуживающий сервер. Для связи с клиентами сервер использует TCP. Клиентская программа позволяет пользователям начинать разговор, присоединяться к уже ведущейся дискуссии и покидать сессию. Разработайте и реализуйте код координатора, сервера и клиента.

Глава 7. Прикладной уровень

Изучив основы компьютерных сетей, мы переходим к уровню, на котором находятся приложения. Все уровни, расположенные ниже прикладного, занимаются доставкой данных, но не выполняют никакой практической работы для пользователя. В этой главе мы изучим реальные сетевые приложения.

Прикладной уровень также нуждается в служебных протоколах, способных обеспечить функционирование многочисленных приложений. И прежде чем изучать сами приложения, мы познакомимся с одним из таких протоколов. Речь идет о службе имен доменов, которая сопоставляет доменные имена с IP-адресами. Далее будут рассмотрены три реальных приложения: электронная почта, Всемирная паутина (или просто «интернет») и мультимедийные приложения, включая современную потоковую видеопередачу. В конце главы мы поговорим о распределении контента, в том числе об одноранговых (пиринговых) сетях и сетях доставки контента.


7.1. Служба имен доменов DNS

Теоретически программа может обращаться к веб-страницам, почтовым ящикам и другим ресурсам, используя сетевые адреса (то есть IP-адреса) компьютеров, на которых они хранятся, однако пользователям тяжело запоминать эти адреса. Кроме того, размещение веб-страницы компании по адресу 128.111.24.41 будет означать, что в случае переезда сервера компании на новый компьютер потребуется сообщить новый IP-адрес всем заинтересованным лицам. Хотя такой переезд веб-сайта с одного IP-адреса на другой кажется маловероятным, в действительности это вполне распространенное явление при балансировке нагрузки. Например, контент многих современных сайтов размещается на большом количестве компьютеров, часто в территориально разных кластерах. А хостинг-провайдерам иногда нужно переместить соединение какого-нибудь клиента с одного веб-сервера на другой. Проще всего это сделать с помощью службы имен доменов (Domain Name System, DNS).

Имена компьютеров отделяются от их адресов путем использования удобочитаемых высокоуровневых имен. Таким образом, к веб-серверу компании можно обращаться по имени www.cs.uchicago.edu, независимо от того, какой у него IP-адрес. Поскольку устройства на сетевом пути пересылают трафик к получателю, руководствуясь его IP-адресом, эти удобочитаемые доменные имена нужно конвертировать в IP-адреса; именно это и делает DNS. В следующих разделах мы узнаем, как DNS выполняет это преобразование и каким изменениям она подверглась за прошедшие десятилетия. В частности, серьезное развитие в последние годы получила защита личной информации пользователей. Мы подробно обсудим эти вопросы и последние разработки в области шифрования DNS, связанные с обеспечением конфиденциальности.


7.1.1. История и общие сведения

Во времена сети ARPANET имена всех компьютеров сети и их IP-адреса сохранялись в файле hosts.txt. Каждую ночь все хосты получали этот файл с сайта, на котором он хранился. В сети, состоящей из нескольких сотен больших компьютеров, работающих в системе с разделением времени, такой подход оправдывал себя.

Однако еще задолго до того, как к сети были подключены миллионы компьютеров, всем стало ясно, что этот способ не может работать вечно. Во-первых, размер файла рано или поздно стал бы слишком большим. Что еще важнее, если не управлять именами хостов централизованно, неизбежно возникнут конфликты имен. В то же время в гигантской международной сети такое управление вряд ли возможно. Для решения всех этих проблем в 1983 году и была разработана DNS. С тех пор она является ключевой составляющей интернета.

DNS представляет собой сочетание иерархической схемы именования с распределенной базой данных, реализующей эту схему. В первую очередь DNS служит для преобразования имен хостов в IP-адреса, но у нее есть и ряд иных применений, которые мы подробно обсудим ниже. Система DNS является одним из наиболее активно развивающихся протоколов интернета. Она описана в документах RFC 1034, RFC 1035, RFC 2181 и доработана в ряде других RFC.


7.1.2. Процесс поиска DNS

DNS работает следующим образом. Для преобразования имени в IP-адрес прикладная программа вызывает библиотечную процедуру (обычно это gethostbyname или ее аналог), передавая ей имя в качестве параметра. Этот процесс иногда называют оконечным распознавателем (stub resolver). Он отправляет запрос с именем локальному DNS-распознавателю, или, как его еще часто называют, локальному рекурсивному распознавателю (local recursive resolver) или просто локальному распознавателю, который выполняет рекурсивный поиск (recursive lookup) имени, используя некоторый набор DNS-распознавателей. В итоге локальный распознаватель возвращает ответ с соответствующим IP-адресом оконечному распознавателю, который затем передает результат той функции, от которой поступил исходный запрос. И запрос, и ответ передаются как UDP-пакеты. После этого, уже имея IP-адрес, программа может связаться с хостом, соответствующим тому DNS-имени, которое она искала. Далее в этой главе мы рассмотрим этот процесс более подробно.

Обычно оконечный распознаватель направляет запрос рекурсивного поиска локальному распознавателю, то есть он просто выдает запрос и ожидает ответа. Локальный распознаватель, в свою очередь, направляет ряд запросов соответствующим серверам имен для каждого элемента именной иерархии. Сервер имен, отвечающий за определенную часть этой иерархии, при этом считается авторитетным сервером имен (authoritative name server) для этого домена. Как мы увидим позже, система DNS использует кэширование, но кэш при этом может устаревать. Авторитетный сервер имен обладает, как понятно из названия, непререкаемым авторитетом. Он по определению всегда прав. Перед тем как переходить к более детальному рассмотрению работы DNS, давайте немного поговорим об иерархии серверов имен DNS и процессе выделения имен.

Получив запрос от оконечного распознавателя хоста, локальный распознаватель осуществляет процесс разрешения имен, пока не найдет нужный ответ (или не найдет его вовсе). Он не возвращает частичные ответы. С другой стороны, корневой сервер имен (и каждый последующий) не отправляет запрос локальному серверу имен рекурсивно. Он возвращает частичный ответ и переходит к следующему запросу. Локальный распознаватель обеспечивает продолжение процесса разрешения имен путем выдачи дальнейших итеративных запросов.

В ходе процесса разрешения имен обычно используются оба механизма. Рекурсивные запросы практически всегда кажутся предпочтительными, но многие серверы имен (особенно корневые) их не обрабатывают. Они слишком загружены. Итеративные запросы перекладывают ответственность на их источник. Для локального сервера имен разумно поддерживать рекурсивные запросы, чтобы предоставлять сервис хостам на своем домене. Эти хосты не обязательно должны быть сконфигурированы для запуска полного сервера имен, достаточно возможности обращения к локальному серверу. Каждый запрос содержит 16-битный идентификатор транзакции; он копируется в ответ, и, таким образом, сервер имен может выдавать необходимые ответы, даже когда поступает много запросов одновременно.

Все ответы, в том числе все возвращенные частичные ответы, хранятся в кэше. Так, если компьютер, расположенный в домене cs.vu.nl, запросит имя cs.uchicago.edu, ответ будет сохранен в кэше. Если вскоре после этого другой хост в домене cs.vu.nl тоже запросит имя cs.uchicago.edu, ответ уже будет известен. Более того, если хост запрашивает другой хост в том же домене, например noise.cs.uchicago.edu, запрос может быть направлен напрямую на авторитетный сервер имен для домена cs.uchicago.edu. Сходным образом, при запросе других доменов по адресу uchicago.edu запрос может быть передан напрямую серверу имен домена uchicago.edu. Использование ответов, сохраненных в кэше, серьезно сокращает количество шагов в запросе и повышает производительность. Такой сценарий на самом деле является худшим из возможных вариантов, так как в кэше нет полезной информации.