Реализация взаимодействия через PIPE

Автор работы: Пользователь скрыл имя, 04 Мая 2014 в 11:08, курсовая работа

Краткое описание

СУБД SQLite является легковеснойвстраиваемой, это значит, что все операции с данными выполняются внутри приложения без использования сервера базы данных. Исходный код данной СУБД находится в свободном доступе. Доступ к данным в базе происходит через подключения к базе данных, которые мы открываем через вызов соответственной функции DLL.
Для взаимодействия приложения с СУБД SQLite в настоящий момент используются различные интерфейсы, такие как встроенный интерфейс SQLite,JDBC, ODBC и т.п. Однако, нет реализации интерфейса, поддерживающего взаимодействие клиента с сервером СУБД при помощи Pipeпод Windows.

Содержание

1. Исследование предметной области…….…………………….…………….…5
1.1. Постановка задачи…....…………………….…………….………………..5
1.2. Описание SQLite……….…………...…….…………….………………….7
1.2.1. Устройство и характеристики СУБД SQLite……………...….........7
1.2.2. Методы работы с базой данных……………………….…………....8
1.3. ОписаниеPIPE под Windows…………...…...…………...………………10
1.3.1. Общие понятия ………………………..…………...……………….10
1.3.2. Именованные каналы………………..……………...……………....10
1.3.3. Методы WinAPI для передачи данных…………......……………...12
2. Замысел технического решения….…………………….…………………….15
2.1. Реализация взаимодействия через PIPE…......…………………………..15
2.2. Исполнение запросов кSQLite…………......………………....………….16
3. Описание программы……………….………..…...………………...………...17
3.1. Сервер………………………………...…...……………………………….17
3.2. Клиент…………………………...…………...…………………………….21
3.3. API……………………….....…………………….………………………...22
4. Заключение……….…………………………………….…………………...…24
5. Список используемой литературы…….…………….……………………….

Прикрепленные файлы: 1 файл

Текст курсовой.docx

— 222.81 Кб (Скачать документ)

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

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

Для осуществления межпроцессного взаимодействия используются такие функции WinAPI как:

    • Для создания именованного канал вызывается функция CreateNamedPipe:

HANDLE WINAPI CreateNamedPipe(

  _In_      LPCTSTR lpName,

  _In_      DWORD dwOpenMode,

  _In_      DWORD dwPipeMode,

  _In_      DWORD nMaxInstances,

  _In_      DWORD nOutBufferSize,

  _In_      DWORD nInBufferSize,

  _In_      DWORD nDefaultTimeOut,

  _In_opt_  LPSECURITY_ATTRIBUTES lpSecurityAttributes

);

    • Для ожидания подключения клиента на сервере вызывается функция ConnectNamedPipe:

BOOL WINAPI ConnectNamedPipe(

  _In_         HANDLE hNamedPipe,

  _Inout_opt_  LPOVERLAPPED lpOverlapped

);

    • Для записи канал инициализируется подобно фалу, то есть используется функция CreateFile:

HANDLE WINAPI CreateFile(

LPCTSTR lpFileName,

  _In_      DWORD dwDesiredAccess,

  _In_      DWORD dwShareMode,

  _In_opt_  LPSECURITY_ATTRIBUTES lpSecurityAttributes,

  _In_      DWORD dwCreationDisposition,

  _In_      DWORD dwFlagsAndAttributes,

  _In_opt_  HANDLE hTemplateFile

);

    • Для передачи данных в канал используется функция WriteFile:

BOOL WINAPI WriteFile(

  _In_         HANDLE hFile,

  _In_         LPCVOID lpBuffer,

  _In_         DWORD nNumberOfBytesToWrite,

  _Out_opt_    LPDWORD lpNumberOfBytesWritten,

  _Inout_opt_  LPOVERLAPPED lpOverlapped

);

    • Чтение из канала производится функцией ReadFile:

BOOL WINAPI ReadFile(

  _In_         HANDLE hFile,

  _Out_        LPVOID lpBuffer,

  _In_         DWORD nNumberOfBytesToRead,

  _Out_opt_    LPDWORD lpNumberOfBytesRead,

  _Inout_opt_  LPOVERLAPPED lpOverlapped

);

    • Закрытие канала производится функцией CloseHandle:

BOOL WINAPI CloseHandle(

  _In_  HANDLE hObject

);

 

 

 
  1. ЗАМЫСЕЛ ТЕХНИЧЕСКОГО РЕШЕНИЯ

Задача по реализации клиентского API к СУБД с помощью PIPE под Windows сводится к 2 основным этапам:

  1. Реализация клиент-серверного API для взаимодействия при помощи PIPE;
  2. Исполнение запроса от клиента на сервере СУБД.

В проекте реализованы SQL команды, не возвращающие ответ пользователю. То есть такие как Insert, Update, Delete и т.п. После исполнения клиент только получает либо ответ об успешном выполнении, либо информацию об ошибке.

    1. Реализация взаимодействия через PIPE

Существует два вида каналов: именованные и анонимные. Анонимные используются для передачи между родительским и дочерним приложением. Так как в данном проекте используются независимые сервер и клиент, анонимные каналы использовать не представляется возможным.

Поэтому для передачи SQL запроса с клиентского приложения на сервер, где находится СУБД SQLite, используется метод взаимодействия при помощи именованных каналов.  При запуске сервера создается именованные канал. После по названию канала клиентское приложение связывается с сервером

Так как с сервером взаимодействует несколько клиентских приложений, возникает проблема идентификации каждого клиента в канале. Для этого используется буферы и маркеры для каждого клиентского приложения.

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

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

Для взаимодействия клиентского и серверного приложения требуются следующие функции:

    • Подключение клиента к серверу;
    • Передача строки запроса, введенной в клиентском приложении пользователем;
    • Прием ответа от сервера о результате исполнения или о возникших ошибках;
    • Отключение клиента от сервера.
    1. Исполнение запросов к SQLite

Во время запуска сервера происходит подключение к СУБД. При подключении создается дескриптор подключения, за счет которого выполнятся все запросы к базе данных.

Так как сервер многопоточный, дескриптор подключения должен быть доступен всем потокам. Синхронизация доступа и блокировки реализованы в СУБД SQLite, поэтому достаточно отправить запрос на выполнение.

После исполнения запроса проводится проверка на возникшие ошибки. Если произошла ошибка, то информация о ней передается на клиент а СУБД никаких изменений в базу данных не вносит.

В случае успешного выполнения запроса клиенту передается ответ об успешном выполнении, а на сервере управление переходит к вызвавшему потоку.

 

 
  1. ОПИСАНИЕ ПРОГРАММЫ
    1. Сервер

Структурная схема сервера представлена на «рис.1». Интерфейс сервера представлен на «рис.2».

При запуске сервера создается именованный канал с именем \\.\\pipe\\SamplePipe. Канал открывается для чтения и записи. Режим приема сообщений. Буферы размером в 512 байт.

Рис.1. Структурная схема сервера

 

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

Так как сервер многопоточный, дескриптор подключения для всех потоков один. Таким образом, для всех клиентов существует одно подключение к базе данных.

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

Блок-схема работы потока представлена на «рис.3». В созданном потоке происходит чтение входящей строки. Для этого вызывается функция ReadFile(). Если во время чтения не произошло ошибок, то вызывается функция void GetAnswerToRequest( wchar_t* pchRequest, LPTSTR pchReply, LPDWORD pchBytes ). Блок-схема работы функции GetAnswerToRequest представлена на рис.4.

Так как API SQLite работает со строками типа char, а при работе с PIPE строки типа wchar_t. Поэтому перед передачей SQL запроса происходит приведение его типа к char. После передачи полученного запроса и его исполнения клиенту передается либо строка с ошибкой, либо ответ, что запрос исполнен успешно.

 

Рис.2. Результат работы серверного приложения после запуска

Рис.3. Структурная схема одного потока на сервере

 

 

Рис.4. Структурная схема функции GetAnswerToRequest

 

    1. Клиент

Результат запуска клиента представлен на «рис.5». Его структурная схема клиента представлена на «рис.6».

Основной задачей клиентского приложения является демонстрация возможностей  разработанного API. Для этого создается объект server, конструкотору которого передается имя канала, к которому подключиться.

 

 

Рис.5. Результат работы клиентского приложения после запуска

 

Рис.6. Структурная схема клиентского приложения

 

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

После исполнения запроса клиент прекращает свою работу.

 

    1. API

Для взаимодействия с сервером реализован класс Pipe_SERVER, исходный код которого находится в файле «SQLite_API.h» и представлен в Приложении. Функции в API:

    • int connect() – функция для подключения к серверу. Возвращает 0, если подключение прошло успешно. В случае ошибки происходит вывод текста ошибки и функция возвращает 1.
    • int send_data(wchar_t *chRequest, int length) – функция для передачи строки запроса chRequest длиной length. В случае успешной передачи возвращает 0. Иначе возвращает 1 и отключает от сервера.
    • int recieve_data() – функция, предназначенная для получения ответа от сервера. Возвращает 0 в случае успешного исполнения. В случае ошибки возвращает 0 и отключает от сервера.
    • void cleanup() – функция для отключения от сервера.

Для использования функция API создается объект класса Pipe_SERVER, с помощью которого и происходит все взаимодействие.

В конструкторе класса происходит предварительная настройка подключения, то есть инициализация имени канала.

Для подключения к серверу требуется вызвать метод connect(). В этом методе с помощью функции WinAPI CreateFile() происходит инициализация канала на стороне клиента. То есть сохраняется HANDLE, через который происходит запись и прием сообщений.

С помощью метода send_data (wchar_t *chRequest, int length) производится передача строки chRequest длиной length байт. Передача запроса выполняется при помощи вызова функции WriteFile().

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

С помощью метода cleanup() производится отключение от сервера, вызывая функцию CloseHandle(). После закрытия соединения вся работа с объектом завершается.

Заново можно использовать существующий объект соединения, вызвав функцию connect(). Объект нельзя связать с другим сервером.

 

 
  1. ЗАКЛЮЧЕНИЕ

В заключение следует сделать вывод, что использование Pipe на ОС Windows упрощает разработку различных клиент-серверных приложений. Засчет того, что в Pipe используются такие же методы WinAPI, как и для работы с файлами, время разработки существенно сокращается.

В ходе выполнения курсового проекта был разработан интерфейс, позволяющий с помощью Pipe в ОС Windows реализовать взаимосвязь клиентского приложения с сервером СУБД.

Данный интерфейс не требует привязки к определенной СУБД так как передается только SQL запрос. А сами алгоритмы работы с СУБД реализованы на стороне сервера. Есть возможность использовать на сервере любой интерфейс для работы с СУБД.

С помощью разработанного API  появляется возможность использования БД не на локальном компьютере, а на сервере в локальной сети. Для этого требуется только задать требуемое имя канала.

Так как разработанный API является прослойкой между клиентом и сервером и выполняет транспортные функции, то имеется возможность увеличения функциональности сервера и клиента без внесения изменений в API.  

5. СПИСОК ИСПОЛЬЗУЕМОЙ ЛИТЕРАТУРЫ

  1. http://msdn.microsoft.com
  2. http://www.sqlite.org
  3. Программирование для Windows NT. - Александр Фролов, Григорий фролов. Том 27, часть 2. М.: Диалог-МИФИ, 1996
  4. Системы баз данных. Полный курс. –  Гарсиа-Молина Г.,Ульман Дж., Уидом Дж. Вильямс, 2003.–1088с.

 

  1. C++ для профессионалов. - Николас А. Солтер, Майкл Л. Клепер. Диалектика, Вильямс, 2006
  2. Using SQLite. - Jay A. Kreibich - O'Reilly Media 2010

 

 

 

 

 

ПРИЛОЖЕНИЕ 1

CppNamedPipeServer.cpp

#include <windows.h>

#include <stdio.h>

#include <tchar.h>

#include <strsafe.h>

#include "iostream"

Информация о работе Реализация взаимодействия через PIPE