Автор работы: Пользователь скрыл имя, 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. Список используемой литературы…….…………….……………………….
#include <string>
#include "atlstr.h"
#include "sqlite3.h"
#define BUFSIZE 512
using namespace std;
DWORD WINAPI InstanceThread(LPVOID);
VOID GetAnswerToRequest(LPTSTR, LPTSTR, LPDWORD);
sqlite3 *db = 0; // хэндл объекта соединение к БД
char *err = 0;
int _tmain(VOID)
{
BOOL fConnected = FALSE;
DWORD dwThreadId = 0;
HANDLE hPipe = INVALID_HANDLE_VALUE, hThread = NULL;
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\SamplePipe"
if( sqlite3_open("db1.dblite", &db) )
printf("Error in open/create DB: %s\n", sqlite3_errmsg(db));
for (;;)
{
_tprintf( TEXT("\nPipe Server: Main thread awaiting client connection on %s\n"), lpszPipename);
hPipe = CreateNamedPipe(
lpszPipename, // pipe name
PIPE_ACCESS_DUPLEX, // read/write access
PIPE_TYPE_MESSAGE | // message type pipe
PIPE_READMODE_MESSAGE | // message-read mode
PIPE_WAIT, // blocking mode
PIPE_UNLIMITED_INSTANCES, // max. instances
BUFSIZE, // output buffer size
BUFSIZE, // input buffer size
0, // client time-out
NULL); // default security attribute
if (hPipe == INVALID_HANDLE_VALUE)
{
_tprintf(TEXT("CreateNamedPipe failed, GLE=%d.\n"), GetLastError());
return -1;
}
fConnected = ConnectNamedPipe(hPipe, NULL) ?
TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
if (fConnected)
{
printf("Client connected, creating a processing thread.\n");
// Create a thread for this client.
hThread = CreateThread(
NULL, // no security attribute
0, // default stack size
InstanceThread, // thread proc
(LPVOID) hPipe, // thread parameter
0, // not suspended
&dwThreadId); // returns thread ID
if (hThread == NULL)
{
_tprintf(TEXT("CreateThread failed, GLE=%d.\n"), GetLastError());
return -1;
}
else CloseHandle(hThread);
}
else
// The client could not connect, so close the pipe.
CloseHandle(hPipe);
}
return 0;
}
DWORD WINAPI InstanceThread(LPVOID lpvParam)
{
HANDLE hHeap = GetProcessHeap();
TCHAR* pchRequest = (TCHAR*)HeapAlloc(hHeap, 0, BUFSIZE*sizeof(TCHAR));
TCHAR* pchReply = (TCHAR*)HeapAlloc(hHeap, 0, BUFSIZE*sizeof(TCHAR));
DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0;
BOOL fSuccess = FALSE;
HANDLE hPipe = NULL;
if (lpvParam == NULL)
{
printf( "\nERROR - Pipe Server Failure:\n");
printf( " InstanceThread got an unexpected NULL value in lpvParam.\n");
printf( " InstanceThread exitting.\n");
if (pchReply != NULL) HeapFree(hHeap, 0, pchReply);
if (pchRequest != NULL) HeapFree(hHeap, 0, pchRequest);
return (DWORD)-1;
}
if (pchRequest == NULL)
{
printf( "\nERROR - Pipe Server Failure:\n");
printf( " InstanceThread got an unexpected NULL heap allocation.\n");
printf( " InstanceThread exitting.\n");
if (pchReply != NULL) HeapFree(hHeap, 0, pchReply);
return (DWORD)-1;
}
if (pchReply == NULL)
{
printf( "\nERROR - Pipe Server Failure:\n");
printf( " InstanceThread got an unexpected NULL heap allocation.\n");
printf( " InstanceThread exitting.\n");
if (pchRequest != NULL) HeapFree(hHeap, 0, pchRequest);
return (DWORD)-1;
}
// Print verbose messages. In production code, this should be for debugging only.
printf("InstanceThread created, receiving and processing messages.\n");
hPipe = (HANDLE) lpvParam;
// Loop until done reading
while (1)
{
fSuccess = ReadFile(
hPipe, // handle to pipe
pchRequest, // buffer to receive data
BUFSIZE*sizeof(TCHAR), // size of buffer
&cbBytesRead, // number of bytes read
NULL); // not overlapped I/O
if (!fSuccess || cbBytesRead == 0)
{
if (GetLastError() == ERROR_BROKEN_PIPE)
{
_tprintf(TEXT("InstanceThread: client disconnected.\n"), GetLastError());
}
else
{
_tprintf(TEXT("InstanceThread ReadFile failed, GLE=%d.\n"), GetLastError());
}
break;
}
// Process the incoming message.
GetAnswerToRequest(pchRequest, pchReply, &cbReplyBytes);
// Write the reply to the pipe.
fSuccess = WriteFile(
hPipe, // handle to pipe
pchReply, // buffer to write from
cbReplyBytes, // number of bytes to write
&cbWritten, // number of bytes written
NULL); // not overlapped I/O
if (!fSuccess || cbReplyBytes != cbWritten)
{
_tprintf(TEXT("InstanceThread WriteFile failed, GLE=%d.\n"), GetLastError());
break;
}
}
FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
HeapFree(hHeap, 0, pchRequest);
HeapFree(hHeap, 0, pchReply);
printf("InstanceThread exitting.\n");
return 1;
}
VOID GetAnswerToRequest( wchar_t* pchRequest,
LPTSTR pchReply,
LPDWORD pchBytes )
{
_tprintf( TEXT("Client Request String:\"%s\"\n"), pchRequest );
wcout << pchRequest << _T(" (wchar_t *)") << endl;
size_t origsize = wcslen(pchRequest) + 1;
size_t convertedChars = 0;
const size_t newsize = origsize*2;
char *sqlreq = new char[newsize];
wcstombs_s(&convertedChars, sqlreq, newsize, pchRequest, _TRUNCATE);
cout <<"SQL request: "<< sqlreq << endl;
wchar_t *response;
response = L" ";
if (sqlite3_exec(db, sqlreq, 0, 0, &err))
{
printf("SQL Error: %sn", err);
sqlite3_free(err);
response = L"SQL Error";
} else response = L"Success";
// Check the outgoing message to make sure it's not too long for the buffer.
if (FAILED(StringCchCopy( pchReply, BUFSIZE, response )))
{
*pchBytes = 0;
pchReply[0] = 0;
printf("StringCchCopy failed, no outgoing message.\n");
return;
}
*pchBytes = (lstrlen(pchReply)+1)*sizeof(
}
ПРИЛОЖЕНИЕ 2
CppNamedPipeClient.cpp
#pragma region Includes
#include <stdio.h>
#include <windows.h>
#include "iostream"
#pragma endregion
#include "SQLite_API.h"
// The full name of the pipe in the format of \\servername\pipe\pipename.
#define SERVER_NAME L"."
#define PIPE_NAME L"SamplePipe"
#define FULL_PIPE_NAME L"\\\\" SERVER_NAME L"\\pipe\\" PIPE_NAME
#define BUFFER_SIZE 1024
// Request message from client to server.
#define REQUEST_MESSAGE L"CREATE TABLE IF NOT EXISTS foo(a,b,c); INSERT INTO FOO VALUES(1,2,3); INSERT INTO FOO SELECT * FROM FOO;"
using namespace std;
int wmain(int argc, wchar_t* argv[])
{
wchar_t req_str[200];
Pipe_SERVER server(FULL_PIPE_NAME);
// Try to open the named pipe identified by the pipe name.
int err = server.connect();
if (err == 1) {
cout << "Error while connection";
server.cleanup();
system("pause");
return 0;
}
wprintf(L"Enter Request:");
wscanf( L"%[^\r\n]", req_str );
//
// Send a request from client to server
//
if (server.send_data(req_str, sizeof(req_str)) !=0 ) {
cout << "error while sending data";
server.cleanup();
system("pause");
return 0;
} else {
cout << "Success in sending"<<endl;
}
//
// Receive a response from server.
//
//
//Code from exhample
if (server.recieve_data() == 0)
wprintf(L"Recieved successfull. Data: \"%s\"\n", server.chResponse);
//
server.cleanup();
system("pause");
return server.dwError;
}
ПРИЛОЖЕНИЕ 3
SQLite_API.h
#include <stdio.h>
#include <windows.h>
#include "iostream"
#pragma endregion
class Pipe_SERVER
{
private:
HANDLE hPipe;
LPCWSTR FULL_PIPE_NAME;
static const int BUFFER_SIZE = 1024;
public:
DWORD dwError;
TCHAR chResponse[BUFFER_SIZE]; //Answers from server
Pipe_SERVER(LPCWSTR PIPE_NAME){
hPipe = INVALID_HANDLE_VALUE;
dwError = ERROR_SUCCESS;
FULL_PIPE_NAME = PIPE_NAME;
}
int connect(){
while (TRUE){
hPipe = CreateFile(
FULL_PIPE_NAME,
GENERIC_READ | GENERIC_WRITE, // Read and write access
0,
NULL,
OPEN_EXISTING,
0,
NULL
);
if (hPipe != INVALID_HANDLE_VALUE)
{
wprintf(L"The named pipe (%s) is connected.\n", FULL_PIPE_NAME);
break;
}
dwError = GetLastError();
if (ERROR_PIPE_BUSY != dwError)
{
wprintf(L"Unable to open named pipe w/err 0x%08lx\n", dwError);
return 1;
}
// All pipe instances are busy, so wait for 5 seconds.
if (!WaitNamedPipe(FULL_PIPE_
{
dwError = GetLastError();
wprintf(L"Could not open pipe: 5 second wait timed out.");
return 1;
}
}
// Set the read mode and the blocking mode of the named pipe. In this
// sample, we set data to be read from the pipe as a stream of messages.
DWORD dwMode = PIPE_READMODE_MESSAGE;
if (!SetNamedPipeHandleState(
{
dwError = GetLastError();
wprintf(L"
return 0;
}
return 0;
}
//
int send_data(wchar_t *chRequest, int length){
DWORD cbWritten;
wprintf( L"Sizeof %d of message: %s\n",length, chRequest);
;
if (!WriteFile(
hPipe, // Handle of the pipe
chRequest, // Message to be written
length, // Number of bytes to write
&cbWritten, // Number of bytes written
NULL // Not overlapped
))
{
dwError = GetLastError();
wprintf(L"WriteFile to pipe failed w/err 0x%08lx\n", dwError);
return 1;
cleanup();
}
wprintf(L"Send %ld bytes to server: \"%s\"\n", cbWritten, chRequest);
return 0;
}
int recieve_data(){
BOOL fFinishRead = FALSE;
do
{
DWORD cbResponse, cbRead;
cbResponse = sizeof(chResponse);
fFinishRead = ReadFile(
hPipe, // Handle of the pipe
chResponse, // Buffer to receive the reply
cbResponse, // Size of buffer in bytes
&cbRead, // Number of bytes read
NULL // Not overlapped
);
if (!fFinishRead && ERROR_MORE_DATA != GetLastError())
{
dwError = GetLastError();
wprintf(L"ReadFile from pipe failed w/err 0x%08lx\n", dwError);
cleanup();
return 1;
}
} while (!fFinishRead); // Repeat loop if ERROR_MORE_DATA