Онлайн
библиотека книг
Книги онлайн » Разная литература » Компьютерные сети. 6-е изд. - Эндрю Таненбаум

Шрифт:

-
+

Закладка:

Сделать
1 ... 199 200 201 202 203 204 205 206 207 ... 335
Перейти на страницу:
6.29. Шаг 1 заключается в вызове клиентом клиентской заглушки. Это локальный вызов процедуры, при котором параметры самым обычным образом помещаются в стек. Шаг 2 состоит в упаковке параметров клиентской заглушки в сообщение и в осуществлении системного вызова для его отправки. Упаковка параметров называется маршалингом (marshaling). На шаге 3 операционная система передает сообщение с клиентского устройства на сервер. Шаг 4 заключается в том, что операционная система передает входящий пакет серверной заглушке. На шаге 5 серверная заглушка вызывает серверную процедуру с распакованными параметрами. При ответе выполняются те же самые шаги, но передача происходит в обратном направлении.

Илл. 6.29. Этапы выполнения удаленного вызова процедуры. Серым цветом выделены заглушки

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

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

Иногда с помощью некоторых уловок все же удается передать указатели. Допустим, первым параметром является указатель на целое число k. Клиентская заглушка может выполнить маршалинг k и передать его серверу. Серверная заглушка создаст указатель на полученную переменную k и передаст его серверной процедуре. Именно этого она и ждет. Когда серверная процедура возвращает управление серверной заглушке, последняя отправляет k обратно клиенту, где обновленное значение этой переменной записывается вместо старого (если оно было изменено сервером). По сути, стандартная последовательность действий, выполняемая при передаче параметра по ссылке, заменилась прямой и обратной передачей копии параметра. Увы, этот трюк не всегда удается применить, в частности, нельзя это сделать, если указатель ссылается на граф или иную сложную структуру данных. Как мы увидим далее, по этой причине на параметры удаленно вызываемых процедур должны накладываться определенные ограничения.

Вторая проблема заключается в том, что в языках со слабой типизацией данных (например, в C) вполне допустимо написание процедуры, которая подсчитывает скалярное произведение двух векторов (массивов), без указания их размеров. Каждая из этих структур в качестве ограничителя имеет какое-то значение, известное только вызывающей и вызываемой процедурам. В этих обстоятельствах клиентская заглушка не способна запаковать параметры: нет никакой возможности определить их размеры.

Третья проблема состоит в том, что не всегда можно распознать типы параметров по спецификации или по самому коду. В качестве примера приведем процедуру printf, у которой может быть любое число параметров (не меньше одного), и они могут представлять собой произвольную смесь различных целочисленных (int, short, long), а также символьных и строковых параметров, чисел различной длины с плавающей запятой и др. Задача удаленного вызова процедуры printf может оказаться практически невыполнимой из-за такой своеобразной толерантности языка С. Однако не существует правила, говорящего, что удаленный вызов процедур возможен, только если используется любой другой язык кроме С (С++). Это подорвало бы репутацию метода RPC среди программистов.

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

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

С точки зрения протоколов транспортного уровня UDP является хорошей основой для реализации RPC. В самом простом случае запросы и ответы можно отправлять в одном UDP-пакете, а обработка может быть очень быстрой. Однако для реализации этой идеи потребуются и другие механизмы. На случай потери запроса или ответа клиенту необходим таймер, отсчитывающий время до повторной отправки пакета. Обратите внимание, что ответ служит неявным подтверждением запроса, поэтому отдельное подтверждение не требуется. Иногда параметры или результаты могут превысить максимальный размер UDP-пакета. Тогда потребуется некий протокол, позволяющий «разбирать» большие сообщения перед отправкой и затем корректно собирать их заново. Если возможно пересечение многочисленных запросов и ответов (как при параллельном программировании), соответствие ответа запросу указывается с помощью специальной метки.

Проблема более высокого уровня связана с тем, что операция может не быть идемпотентной (то есть ее нельзя повторить без риска сбоя). В простом случае мы имеем дело с идемпотентными операциями, такими как DNS-запросы и ответы. Клиент может повторно передавать такие пакеты сколько угодно, ничем не рискуя, до тех пор пока не придет ответ. Пакет может не дойти до сервера, а ответ может потеряться — это неважно. В любом случае, когда ответ придет, он будет тем же (если, конечно, за это время не обновится база данных DNS). Но не все операции идемпотентны: например, если они обладают важными побочными эффектами вроде изменения счетчика. RPC для таких операций требует более сложной семантики: вызванная процедура не должна выполняться несколько раз. В таких случаях может понадобиться установка TCP-соединения и отправка запроса по TCP, а не по UDP.

6.4.3. Транспортные протоколы реального времени

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

Так возник транспортный протокол реального времени (Real-Time Transport Protocol, RTP). Он описан в RFC 3550 и сегодня широко используется в мультимедиа. Мы опишем два компонента транспортировки данных в реальном времени. Первый из них — протокол RTP, необходимый для пакетной передачи аудио и видео. Второй — обработка данных, необходимая для воспроизведения (в основном со стороны получателя). Эти функции входят в стек протоколов, представленный на илл. 6.30.

1 ... 199 200 201 202 203 204 205 206 207 ... 335
Перейти на страницу:

Еще книги автора «Эндрю Таненбаум»: