Процедура создания соединений использует флаг управления синхронизацией (SYN) и включает обмен тремя сообщениями. Этот обмен был назван трехходовым квитированием. Соединение инициируется при встрече прибывающего сегмента, содержащего SYN, и ожидающего входа TCN, которые создаются командой пользователя OPEN. Соответствие локального и внешнего сокетов определяет, когда соединение было инициировано. Соединение становится "установленным", когда номера последовательности синхронизированы в обоих направлениях. Очистка соединения также включает обмен сегментами, несущими в этом случае управляющий флаг FIN.
Протокол не делает никаких ограничений на повторное использование определенного соединения. Соединение определяется парой сокетов. Новые экземпляры соединения будут называться инкарнациями соединения. При этом возникает проблема: "Как TCP идентифицирует сегменты дубликаты из предыдущих инкарнаций соединения?" Эта проблема становится очевидной, если соединение открывается и закрывается в быстрой последовательности или прерывается в связи с нехваткой памяти, а затем восстанавл ивается.
Чтобы избежать путаницы, необходимо воспрепятствовать использованию сегментов из одной инкарнации соединения, в то время как те же самые номера последовательности от предыдущей инкарнации могут по-прежнему присутствовать в сети. Мы хотим гарантировать это, даже если TCP прерывает работу и теряет всю информацию о номерах последовательности, которые он использует. Когда создается новое соединение, используется генератор начального порядкового номера (ISN), который выбирает новый 32- разрядный ISN. Генератор связан с 32-битными часами (возможно, фиктивными), младший бит которых увеличивается каждые четыре миллисекунды. Таким образом, ISN циклически повторяется примерно каждые 4,55 часов. Так как мы предполагаем, что сегменты будут оставаться в сети не дольше, чем максимальное время жизни сегмента (MSL), и что MSL меньше 4,55 часов, то можно считать, что ISN будет уникальным.
Для каждого соединения существует номер посылаемой последовательности и номер получаемой последовательности. Начальный номер посылаемой последовательности (ISS) выбирается посылающим данные TCP, а начальный номер принимаемой последовательности (1RS) узнается во время процедуры создания соединения. Чтобы соединение было установлено или инициализировано, два TCP должны синхронизировать друг с другом начальные номера последовательностей. Это делается при обмене устанавливающими соединение сегментами, несущими управляющий бит, называемый "SYN" (от слова синхронизация), и начальные номера последовательностей. В качестве сокращения сегменты, переносящие бит SYN, также называются "SYN". Следовательно, решение требует подходящего механизма для выбора начального номера последовательности и небольшого привлечения квитирования для обмена ISN.
Синхронизация требует, чтобы каждая сторона посылала свой собственный начальный номер последовательности и получала подтверждение от другой стороны. Каждая сторона должна также получить начальный номер последовательности другой стороны и послать об этом подтверждение.
1. А —> В SYN мой номер последовательности X
2. А <—- В АСК ваш номер последовательности X
3. А <-- В SYN мой номер последовательности Y
4. А —> В АСК ваш номер последовательности Y
Так как шаги 2 и 3 обычно объединяются в одном сообщении, то последовательность называется трехходовым квитированием. На рис. 2.3 показано, как это выглядит в реальной жизни.
Трехходовое квитирование необходимо в связи с тем, что номера последовательности не связаны с глобальными часами сети, и TCP может иметь другие механизмы для выбора ISN. Получатель первого SYN не может узнать, является ли сегмент задержавшимся старым или нет, если он не помнит последний номер последовательности, использованный соединением (что не всегда возможно). Поэтому он должен запросить отправителя проверить, что TCP не создал сегмент, несущий номер последовательности, который может дублироваться старым сегментом, остающимся в сети. TCP должен оставаться спокойным в течение максимального периода жизни (MSL), прежде чем присваивать какие-либо номера последовательности при запуске или восстановлении после ошибки, при которой память используемых номеров последовательности была стерта. Для этой спецификации MSL задается равным двум минутам. Это инженерный выбор, который может быть изменен, если опыт покажет такую необходимость. Отметим, что если TCP повторно инициализирован, но сохранил в памяти номера последовательности, ему вообще не нужно ждать, он должен лишь использовать номера последовательности, превышающие использованные ранее.
Во всех состояниях, кроме SYN-SENT, все сегменты сброса (RST) контролируются проверкой их полей SEQ. Сброс будет признан действительным, если его номер последовательности находится в пределах окна. В состоянии SYN-SENT (RST получен в ответ на начальный SYN) RST является приемлемым, если поле АСК подтверждает SYN.
Получатель RST сначала проверяет его, а затем изменяет состояние. Если получатель был в состоянии LISTEN, то он его игнорирует. Если получатель был в состоянии SYN-RECErVED, а ранее — в состоянии LISTEN, то получатель возвращается в состояние LISTEN; иначе получатель прерывает соединение и переходит в состояние CLOSED. Если получатель был в другом состоянии, он прерывает соединение, уведомляет пользователя и переходит в состояние CLOSED. Закрытие соединения (CLOSE) является операцией, означающей: "У меня больше нет данных для пересылки". Понятие закрытия дуплексного соединения часто неверно интерпретируется, так как может быть не очевидно, как интерпретировать получающую сторону соединения. Мы выбрали одностороннюю интерпретацию CLOSE. Пользователи, которые делают CLOSE, могут продолжать RECEIVE (получать), пока они не получат сообщение о том, что другая сторона также CLOSED (закрыта). Таким образом, программа могла бы инициировать несколько команд SEND (послать) после команды CLOSE (закрыть), и затем продолжить получать, пока не будет получен сигнал, что команда RECEIVE (получить) не сработала, так как другая сторона закрылась (CLOSED). Мы предполагаем, что TCP будет сигнализировать пользователю, даже если нет никаких ожидающих RECEIVE и другая сторона закрыта, поэтому пользователь сможет аккуратно завершить свою работу. TCP надежно доставит все буферы, посланные до того, как соединение было закрыто, поэтому пользователю, который не ожидает возврата никаких данных, необходимо только подождать сообщения, что соединение успешно закрыто, следовательно, все его данные были получены TCP местом назначения. Пользователи должны продолжать считывание соединений, которые они закрыли для отправки, пока TCP не сообщит об отсутствии данных. Рассмотрим три существующих сценария:
1. Закрытие инициирует пользователь, приказывая TCP закрыть соединение.
2. Закрытие инициирует удаленный TCP, посылая управляющий сигнал FIN.
3. Оба пользователя закрывают соединение одновременно.
Сценарий 1: локальный пользователь инициирует закрытие
В этом случае может быть создан сегмент FIN и помещен в очередь исходящих сегментов. Никакие другие команды SEND пользователя TCP не принимает и входит в состояние FIN-WAIT-1. В этом состоянии допускаются команды RECEIVE (получить). Все сегменты, предшествующие и включающие FIN, будут посылаться повторно, пока не будет подтверждено их получение. Когда другой TCP подтвердит FIN и пошлет свою собственную команду FIN, первый TCP может подтвердить (АСК) этот FIN. Отметим, что TCP, получающий FIN, будет подтверждать (АСК), но не посылать свой собственный FIN, пока его пользователь также не закроет соединение.
Сценарий 2: TCP получает FIN из сети
Если из сети прибывает не вынужденный FIN, то получающий TCP может подтвердить его и сообщить пользователю, что соединение закрывается. Пользователь ответит командой CLOSE, затем TCP может послать FIN другому TCP после отправки всех оставшихся данных. Затем TCP ожидает, пока его собственный FIN не будет подтвержден, после чего удаляет соединение. Если подтверждение АСК не поступает после периода ожидания пользователя, соединение прерывается и об этом сообщается пользователю.
Сценарий 3: оба пользователя закрывают соединение одновременно
Одновременное закрытие пользователями на обоих концах соединения вызывает обмен сегментами FIN. Когда все сегменты, предшествующие FIN, обработаны и подтверждены, каждый TCP может подтвердить полученный FIN. После получения этих АСК оба удалят соединение.
Эта команда выделяет буфер получения, связанный с указанным соединением. Если этой команде не предшествует команда OPEN, или вызывающий процесс не уполномочен использовать это соединение, возвращается ошибка.
В простейшей реализации управление не будет возвращаться вызывающей программе, пока не заполнится буфер или не произойдет какая-нибудь ошибка, но эта схема существенно подвержена блокированию. Более развитая реализация будет позволять нескольким командам RECEIVE ожидать выполнения одновременно. Они будут выполняться по мере поступления сегментов. Эта стратегия позволяет увеличить пропускную способность за счет более развитой схемы (возможно, асинхронной) уведомления вызывающей программы, что был получен PUSH или заполнен буфер. Если прибывает количество данных, достаточное для заполнения буфера до появления PUSH, флаг PUSH в ответ на RECEIVE задаваться не будет. Буфер будет заполнен таким количеством данных, сколько он может вместить. Если до заполнения буфера появляется PUSH, буфер возвращается частично заполненным и с указанием PUSH.
При наличии срочных данных пользователь будет проинформирован об этом, как только они появятся, с помощью сигнала TCP пользователю. Получающий пользователь должен поэтому находиться в "срочном режиме". Если установлен флаг URGENT, остаются дополнительные срочные данные. Если флаг URGENT сброшен, то этот вызов RECEIVE вернул все срочные данные, и пользователь может теперь покинуть "срочный режим". Отметим, что данные, следующие за указателем срочности (несрочные данные), нельзя доставить пользователю в тот же буфер с предшествующими срочными данными, если только граница для пользователя четко не обозначена.
Чтобы различить несколько ожидающих RECEIVE и компенсировать буфер, который не полностью заполнен, код возврата сопровождается указателем буфера и счетчиком байтов, указывающим реальную длину полученных данных.
Альтернативные реализации RECEIVE могут иметь TCP, который выделяет буферную память, или TCP может совместно с пользователем использовать кольцевой буфер.
Close (Закрыть)
Эта команда вызывает закрытие указанного соединения. Если соединение не открыто, или же вызывающий процесс не уполномочен использовать это соединение, возвращается ошибка. Закрытие соединения предназначено для элегантной работы в том смысле, что ожидающие SEND будут переданы (и переданы повторно), когда позволит управление потоком, пока все не будет обслужено. Таким образом, допустимо выполнить несколько вызовов SEND, за которыми следует CLOSE, и ожидать, что все данные будут посланы в место назначения. Также должно быть ясно, что пользователи могли бы продолжать RECEIVE (получать) на закрытых соединениях, так как другая сторона могла бы пытаться передавать свои завершающие данные. Фактически CLOSE означает: "У меня для передачи больше ничего нет", а не "Я больше ничего не буду принимать". Может случиться (если протокол на уровне пользователя не очень хорошо проработан), что сторона не сможет избавиться от всех своих данных до того, как закончится выделенное время. В этом случае CLOSE превратится в ABORT, и закрывающий TCP прервется. Пользователь может закрыть соединение в любое время по своей собственной инициативе или в ответ на различные предложения от TCP (например, выполнено удаленное закрытие, превышена задержка передачи, место назначения недоступно).
Так как закрытие соединения требует коммуникации с внешним TCP, соединение может оставаться в закрытом состоянии в течение некоторого времени. Попытки повторно открыть соединение, прежде чем TCP ответит на команду CLOSE, будет приводить к сообщению об ошибке. CLOSE также подразумевает вызов функции push (выталкивания данных).
Status Abort (Прервать)
Эта команда вызывает прерывание всех ожидающих SEND и RECEIVE, удаление ТСВ и отправку специального сообщения RESET для TCP на другой стороне соединения. В зависимости от реализации пользователи могут получать указания о прерывании для каждой ожидающей команды SEND или RECEIVE или просто получить подтверждение команды ABORT.
Заголовок SPX состоит из следующих семи полей:
• Управление соединением — 1 байт
• Тип потока данных — 1 байт
• Идентификатор соединения источника — 2 байта
• Идентификатор соединения места назначения — 2 байта
• Номер последовательности - 2 байта
• Номер подтверждения — 2 байта
• Номер размещения — 2 байта
Управление соединением Остановимся на некоторых функциях, предоставляемых полем управления соединением. Эквивалент флагов TCP, которые были показаны в главе 2, управление соединением предоставляет механизм двунаправленного потока данных, управления перегрузкой и другие связанные с этим возможности. Поле управления соединением указывает три типа пакетов управления соединением. Эти значения могут быть либо логическими, либо могут быть заданы вместе с несколькими флагами. Сначала рассмотрим флаг конца сообщения.
• Флаг "Конец сообщения" (End-of-message). Этот флаг устанавливается, когда в поле управления соединением появляется 0x10. Он используется для указания конца сообщения партнеру по передаче. Так как SPX является транспортным протоколом на основе сообщений, посылающая сторона задает этот флаг для указания, что сообщение завершено. После того как получающая сторона получит этот пакет, она передаст данные в буфер сообщения вышележащего приложения. Это не запрос конца соединения, но скорее указание, что текущий обмен сообщениями закончился.
• Флаг "Требуется подтверждение" (Acknowledgment-Required). Флаг требования подтверждения устанавливается, когда в поле управления соединением появляется 0x40. Он используется для указания, что данные были посланы партнеру по передаче и требуется подтверждение. Прежде чем будут отправлены новые данные, должно быть получено подтверждение для этого пакета.
• SPX требует подтверждения посланных данных; когда они получены, устанавливает флаг, сигнализирующий "конец сообщения" для партнера. Число является комбинацией 0x40 и 0x10 и равно 0x50.
• Флаг "Системный пакет" (System-Packet). Флаг системного пакета устанавливается, когда в поле управления соединением появляется 0x80. Это пакет подтверждения, используемый внутренне протоколом SPX для подтверждения, что партнер по сеансу работает и соединение существует. Это сообщение типа "Я здесь".
• Флаг "Комбинация системных пакетов" (System-Packet combination). Флаг комбинации системных пакетов устанавливается, когда в поле управления соединением появляется ОхСО. ОхСО является суммой 0x80 и 0x40. Он используется внутренне протоколом SPX, показывая, что соединение все еще существует, требуя подтверждения (АСК) от партнера по коммуникации. Это пакет типа "Вы еще здесь?".
Протокол блоков сообщений сервера (SMB — Server Message Blocks) является рабочей лошадкой мира Windows NT и Windows 2000. Он используется между компьютерами для общего доступа к файлам, принтерам, последовательным портам и для коммуникационных абстракций, таких как именованные каналы и почтовые ящики. SMB является клиент-серверным протоколом типа запрос-ответ.
Протокол SMB превратился в общую файловую систему Интернета (Common Internet File System, CIFS). CIFS предоставляет межплатформенный механизм клиентских систем для запроса служб файлов и печати на серверных системах. Он поддерживает файлы и печать, используя команды доступа open (открыть), close (закрыть), read (читать), write (писать) и seek (искать). Кроме того, он поддерживает доступ к файлам и записям как в блокированном, так и в неблокированном режиме. Когда приложение блокирует файл, ему не могут помешать другие приложения. Блокированные файл или запись недоступны не блокирующим приложениям.
SMB предоставляет кэширование с опережающим чтением и с обратной записью. Это безопасные операции до тех пор, пока только один клиент имеет доступ к файлу. Кэширование чтения и оптимизация упреждающего чтения являются безопасными при доступе к файлу или в режиме только чтения. Если несколько клиентов пытаются одновременно записывать в файл, то ничто не будет безопасным; поэтому все файловые операции должны управляться на сервере. SMB уведомляет обращающегося к файлу клиента об изменениях в режиме доступа, чтобы клиент мог использовать оптимальный метод доступа.
Приложения регистрируются для уведомления сервером об изменениях содержимого файла или каталога. Это позволяет приложению знать, когда обновить изображение, не требуя от него постоянно запрашивать сервер.
Существует почти столько же различных версий протокола SMB, сколько и поставщиков программного обеспечения. Каждая версия предоставляет дополнительные функции, свойства и средства. Чтобы справиться с этим изобилием, SMB выполняет так называемое согласование диалектов. Когда два компьютера вступают в контакт, они согласовывают диалект или версию SMB, которая будет использоваться при их общении. Это критический шаг в терминах как производительности, так и безошибочной коммуникации, так как каждый диалект может предоставлять различные сообщения, а также изменения в полях и семантике существующих сообщений других диалектов. В дополнение к обычным атрибутам файлов, например, времени создания и модификации, такими приложениями, как Word могут добавляться другие элементы, чтобы включить, например, имя автора или описание содержимого.
Протокол может поддерживать виртуальные тома, используя файловую систему, которая может охватывать несколько томов и серверов, но выглядеть при этом для клиентской машины как находящаяся на одном сервере. Файлы и каталоги поддерева могут перемещаться на другие серверы, имена при этом изменять не придется. В этом случае не нужно будет делать изменения на настольном компьютере, когда делаются изменения на сервере. Эти поддеревья могут также реплицироваться для выравнивания нагрузки и устойчивости к ошибкам. Когда клиент запрашивает файл, SMB использует направления для пересылки клиента на сервер, который содержит данные. Все это происходит за сценой без вмешательства клиента.
SMB позволяет клиенту преобразовывать имена серверов с помощью DNS, WINS, LMHOSTS или любого другого механизма преобразования имен. Это перемещает нас из неструктурированного, "плоского" пространства серверных имен в иерархически организованное пространство, поддерживающее более широкий диапазон взаимодействия. Чтобы сберечь полосу пропускания, SMB может пакетировать запросы в одном сообщении для минимизации задержки перемещения туда и обратно, даже когда более поздние запросы зависят от результатов предыдущих; он поддерживает также имена файлов в кодировке Unicode.
Обзор работы SM В
Для получения доступа к файлу на сервере клиентское приложение должно разобрать полное имя файла, чтобы определить имя сервера и относительное имя на этом сервере, разрешить имя сервера в адрес транспортировки, создать соединение с сервером и затем обменяться сообщениями. Если имя сервера было ранее разрешено, то оно может находиться в кэше, поэтому разрешение имени может не понадобиться. Кроме того, если предыдущее соединение все еще доступно, то новое соединение тогда не потребуется. Этот процесс повторяется множество раз в течение нормального рабочего дня. Если соединение простаивало в течение некоторого времени, оно будет разорвано.
