Файл: Технология «клиент-сервер».pdf

ВУЗ: Не указан

Категория: Курсовая работа

Дисциплина: Не указана

Добавлен: 19.06.2023

Просмотров: 37

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Глава 1.4. Роль протоколов TCP и UDP в модели «клиент-сервер»

При реализации клиент-серверного приложения, работающего в рамках локальной сети, где показатель ошибок и потерь при передаче данных заведомо низок, вследствие меньшего количества промежуточных узлов, а также зачастую меньшей загруженности каналов, либо же при работе через высоконадежные глобальные каналы связи, взаимодействие может быть реализовано посредством простого протокола, не требующего установления соединения. Использование не требующего соединения протокола дает существенный выигрыш в эффективности. До тех пор пока сообщения не начнут пропадать или повреждаться, можно вполне успешно применять протокол типа запрос-ответ.[11]

Таким протоколом является UDP (User Datagram Protocol) реализующий так называемый «ненадежный сервис по возможности», который не гарантирует доставку сообщений адресату. Протокол UDP добавляет к каждому отдельному сообщению свой 8-байтный заголовок, формируя из этих сообщений собственные протокольные единицы, называемые UDP-дейтаграммами, и передает их нижележащему протоколу IP.[12]

Альтернативой данному протоколу является TCP (Transmission Control Protocol) надежный протокол с установкой соединения, подходящий для работы поверх менее стабильных глобальных каналов связи. При его использовании, прежде чем посылать запрос серверу, клиент должен установить с ним соединение. Сервер обычно использует это-же соединение для посылки ответного сообщения. Протокол TCP рассматривает информацию, поступающую к нему, как неструктурированный поток байтов. Из этого потока вырезается некоторая непрерывная часть данных, называемая сегментом и снабжается заголовком.[13]

В отличии от протокола UDP, который создает свои дейтаграммы на основе логически обособленных единиц данных – сообщений, генерируемых приложениями, протокол TCP делит поток данных на сегменты без учета их смысла и внутренней структуры.[14]

Заголовок TCP содержит значительно больше полей, чем заголовок UDP. Однобитные поля несущие служебную информацию называются флагами, или кодовыми битами. Следующие флаги являются ключевыми при рассмотрении работы протокола:


- SYN – запрос на установку соединения

- ACK – квитанция подтверждения на принятый сегмент

- RST – запрос на восстановление соединения

- FIN – признак достижения последнего байта в потоке

Так же ключевыми для работы протокола являются поля:

- Последовательный номер (sequence number) – номер первого байта данных в передаваемом сегменте

- Подтвержденный номер (Acknowledgement number) – номер последнего байта данных в передаваемом сегменте

Для обеспечения надежной передачи протокол TCP использует метод продвижения данных с установкой логического соединения. Логическое соединение состоит из двух потоков данных – от клиента серверу и от сервера к клиенту. Это позволяет участникам обмена данных следить за тем чтобы данные не были искажены, потеряны или продублированы, а также позволяет получателю восстановить правильную последовательность полученных данных.

Установление логического канала производится с помощью механизма трехстороннего квитирования. При установлении соединения, модули TCP участников обмена договариваются между собой о следующих параметрах:

- максимальный размер сегмента который сторона готова принимать

- максимальное количество сегментов которое сторона готова принимать, даже если квитанции о получении предыдущих сегментов ещё не были получены (размер окна)

- начальный порядковый номер байта, с которого начинается отсчет потока данных в поле последовательный номер (sequence number)

Инициирует соединение клиент, отправляя сегмент, в котором флаг SYN установлен в 1 и указано номер последовательности X с которого будет вестись отсчет данных переданных клиентом.

Сервер отвечает сегментом с установленным флагом ACK, подтверждающим установку потока данных от клиента к серверу, поле подтвержденного номера увеличивается на единицы от значения начального номера последовательности X. Также устанавливается флаг SYN для запроса канала передачи данных от сервера к клиенту и указывается соответственно номер последовательности Y.

Последним этапом установки соединения клиент отвечает сегментом c установленным флагом ACK, и номером подтверждающей последовательности Y увеличенным на единицу.

После этого любая сторона может начать обмен данными или же разорвать связь, так как протокол TCP является методом одноранговой (равноправной) связи.

Размером окна называют количество сегментов, которое может быть передано в процессе ожидания подтверждения. После того как хост-машина передаст определяемое размером окна количество сегментов, она должна будет получить подтверждение и только потом сможет послать какие-либо другие сообщения. [15]


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

Рисунок 2. Пересылка данных в протоколе TCP при минимальном размере окна (Источник Основы организации сетей Cisco, том 1, испр. изд. : Пер. с англ. А.А. Голубченко — М. : Издательский дом "Вильямc", 2004. – стр 174)

Концепция скользящего окна (sliding window) заключается в том, что для повышения скорости передачи данных отправителю разрешается передать некоторое количество пакетов, не дожидаясь прихода на эти пакеты квитанций.[16]

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

Рисунок 3. Пересылка данных в TCP при увеличении размера окна.

Для использования в клиент-серверной модели так же было разработано расширение T/TCP, транзакционный протокол TCP или протокол TCP для транзакций.[17] В части авторитетной литературы[4] данный протокол упоминается как перспективный. Тем не менее серьезного распространения он не получил, также было обнаружено много уязвимостей данного протокола.[18] В 2011м году вместе с публикацией RFC 6247 данный протокол был признан устаревшим.[19]

При выборе протокола для применения в клиент-серверной архитектуре необходимо учитывать множество факторов, некоторые из которых могут быть решающими.

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


Когда основной задачей является обеспечение высокой производительности и надежности хорошим решением становится использование протокола UDP в сочетании с дополнительными процедурами контроля ошибок и потоков, оптимизированным для конкретного приложения.

К примеру, компания Google в 2012 году представила собственный протокол QUIC работающий поверх протокола UDP и реализующий контроль получения и правильности данных при меньшей задержке и накладных расходах на заголовки пакетов. В дополнение протокол может производит шифрование передаваемых данных, а также не требует трехзвенного квитирования для начала передачи данных. [20] Протокол активно используется в сервисах компании, а его поддержка реализована в их браузере Google Chrome, являющимся самым популярным браузером[21], а так же других браузерах основанных на общей с ним кодовой базе.

Другой известной реализацией контроля надежной доставки и переполнения поверх UDP является протокол μTP (произносится как мю-ти-пи, так же Micro Transport Protocol) разработанный компанией BitTorrent. Данный протокол был разработан и используется в программах пиринговых соединений (от пользователя к пользователю) и обмена файлами. Он позволяет производить более эффективный обмен данными и при этом меньше влиять на производительность других приложений, работающих поверх сети, за счет того, что в отличии от протокола TCP значительно быстрее обнаруживает перегрузку канала и освобождает его для других приложений.

Вывод по главе 1

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

Глава 2. Реализация простейшего приложения-сервера и клиента на языке Python 3

Глава 2.1. Постановка задачи

Для реализации примера архитектуры клиент-сервер мной был выбран язык Python, так как он является простым для освоения и при этом достаточно эффективным. Кроме того, язык является достаточно универсальным, и востребованным, применяется для реализации как простых скриптов и автоматизации, так и крупных решений, таких компаний как DropBox, Google[22], Facebook[23] и Instagram[24]. Одной из любопытных особенностей данного языка является так называемая философия языка[25] из которой выходит особенность синтаксиса. В Python, выделение блоков кода осуществляется с помощью отступов – пробелов и табуляции, то есть в языке отсутствуют привычные для других языков программирования операторные скобки (язык Паскаль) или фигурные скобки (язык Си). Подобный подход позволяет сократить количество строк и символов в программе, и как бы подталкивает к написанию «хорошего», легко читаемого кода. Плохо написанный код, к примеру написанный «сплошняком» без форматирования отступами просто на просто не заработает. Так же данный язык является мульти платформенным и позволяет разрабатывать ПО как для систем Microsoft Windows, для систем Mac OS, а так же для различных версий ОС Linux (и более того во многих дистрибутивах является предустановленным).


Мною будет использоваться версия Python 3.7.2, так как это последняя на данный момент и самая свежая версия, обладающая наиболее полным набором возможностей.[26] Большая часть кода третьей версии языка совместима с интерпретаторами второй версии, однако существует и множество изменений и нюансов, необходимо это учитывать при портировании итогового кода в версию для Python 2.

Для упрощения разработки, отладки и рефакторинга кода мной будет использоваться среда разработки (IDE) от фирмы JetBrains – Pycharm 2018.2 (Community Edition). Это мощная и бесплатная среда разработки. Она так же обладает одним из преимуществ Python – мульти платформенностью.

Глава 2.2. Реализация приложения-сервера

Для начала будет разработано приложение-сервер, ожидающее подключение и выводящее в консоль сообщение о подключении, базовую информацию о клиенте, а также выводящее в консоль всю информацию, вводимую клиентом.

Для передачи данных от клиента к серверу, нам понадобится сетевое взаимодействие, реализуемое через сокеты (упрощенно сокетом можно считать пару IP-адрес и порт).

Выполним подключение стандартной библиотеки, отвечающей за взаимодействие с сокетами.

import socket

Далее необходимо создать сам объект сокета

serv_socket = socket.socket()

Следующим шагом будет связывание сокета с машиной на которой исполняется данных код, а так же необходимо выбрать номер используемого порта. Номер порта может быть любым от 0 до 65536, однако большинство операционных систем, требуют для использования портов от 0 до 1023 привилегии системного администратора. Во избежание этого выберем порт не входящий в этот диапазон, выбран порт – 3737. Создадим переменные, host и port, данные переменные позволят в будущем легко менять эти параметры. Значение переменной host оставляем пустым, это позволит принимать соединение от любых адресов. Непосредственно привязка выполняется с помощью встроенного в сокет метода – bind().

serv_socket.bind((host, port))

Теперь нам необходимо при помощи ещё одного встроенного метода – listen() запустить прослушивание данного сокета. В качестве параметра, указывается максимальное количество открываемых соединений. Указываем одино, при наличии активного соединения все последующие попытки будут отбрасываться.

serv_socket.listen(1)

Принимаем входящее соединение при помощи метода accept(). Данный метод ожидает входящее соединение и возвращает номер соединения, адрес клиента и порт.