Click here to Skip to main content
15,890,579 members
Articles / Programming Languages / C

A SQLite Server/Client Implementation

Rate me:
Please Sign up or sign in to vote.
4.93/5 (30 votes)
23 Jan 2008CPOL6 min read 270K   6.7K   128   57
Implementing server/client architecture for the great SQLite!

Introduction / Background

Recently, I had to choose SQL Server for a big project I'm working on, and to be honest - I did not like my options. First, there were all those "x vs. y" performance tests on the web, which did not give very good grades for MS-SQL Server (not to mention the costs, or weight of that hog), and then there are also MySQL, PostGRE, and others, but none of them satisfied me. What I wanted was something that allows me to choose exactly what I want from my server, to use a database engine as good as the SQLite... and at no cost.

Which means - I have to write one...

I started out by searching the web, and there was only one serious result, which was Alex K.'s project, from 2004 I think (his project can be found here).

I got his permission to use his code (actually, I asked him right before posting this article...), and I have adopted some of his code, and wrote a lot of new code. Some of the function names may sound familiar for those who were ever introduced to his code.

Anyway, his code has four main problems that I did not like:

  1. He was passing handles (!) over network.
  2. He was compiling statements and stepping each time.
  3. He was actually wrapping SQLite 2 and not SQlite 3...
  4. VC2005 found leaks in the threads!!!

The problem with no. 1 is that it is pretty clear that the communication between the client and the server must be transparent, no handles and such. The problem with no. 2 is that it generates too much overhead. You should execute one SQL query, get the results at once, and that's it! (Anyway, that is how I see it...) The problem with no. 3 is that most people, most importantly me, like to update their SQLite engine when an update comes out and says in big letters "A minor bug was fixed". The problem with no. 4 is eh... Well, I dunno... Do you like memory leaks?

Basically, what I did is this:

I took the sockets handling function, tweaked it a bit, and replaced gethostbyname with getaddrinfo so it can support IPv6. IPv4 is pretty much deprecated. I rewrote the thread handling classes, the same architecture, some differences here and there, but I just had to be sure there are no memory leaks. The stack classes are almost unharmed; the main thing I changed for them is the naming... I also rewrote the handler class, with the same basic architecture and even function names. Also, added support for SQL execution and SELECT queries! :-)

On the client side, I added an interface, which I took completely from my SQLite wrapper classes, so you do not have to parse the tables' results and convert from UTF8... It does it all for you. One more important thing - I have added support for user authentication on the server.

Well, I'm not really going to tell you each and every word of code I wrote there, so you will just have to download and see for yourself. I'm also not planning on writing any kind of documentation here! I do not have the time for it. Besides, the code is pretty much self-explanatory.

Note: If you are planning on compiling for Win2K/Me/98/95, you will have to include wspiapi.h because of my use of getaddrinfo. Seems like before WinXP, IPv6 was not yet the standard as stated in MSDN.

P.S. - If anyone is serious enough and wants to take this SQLite server/client thing forward, be my guest. It will be nice to post on SourceForge or something like that, keep track of things, documentation, etc... I just do not have the time for it...

Using the code

While writing the libraries, I had to write a demo application to test them... so they are attached in the same solution. The solution basically includes: server classes, client classes, server app, and a client test app. If you want to use the code, just include the relevant library. Also, to compile the server library, you have to include the SQLite3 library/DLL/sources, which can be obtained from here. (The sqlite3.h file is expected at the subfolder ./SQLite/.)

Update 21/01/2008: Now the ZIP file comes with SQLite3 sources as well, because it seems like many users here just do not know how to go to the SQLite website, download sources, and include it in the project... I mean, guys! You cannot do that, but you can use SQL???

For the security part: the default mode of the server library is such that no authentication is required. Unless you write an authentication class and attach it to the server. What I did was write an interface class, which you should derive. In the server demo application, I created a class called CINIAuth, which manages users/passwords/permission in an INI file. Of course, this is not the most secure way, but if you need more security, you can easily write a class which encrypts the passwords and store them wherever you like. (Heck! Even in a SQLite DB!)

Update 21/01/2008: The server now encrypts the passwords with SHA512!

Update 21/01/2008: Now, the server can run as a service. It works as a tray icon, and accepts command line arguments:

Arguments:

  • /instsvc - Install as a service.
  • /remsvc - Uninstall service.
  • /minimize - Minimize to tray on startup.
  • /start - Start listening on startup.
  • /port:[port_num] - Set server listen port to [port_num]. (Will not save this port to settings.ini.)
  • /? or /help - This message.

The way I see it, all you have to do now is take a look at the code, and try it... So, go on!

Points of interest

"Did you learn anything interesting/fun/annoying while writing the code? Did you do anything particularly clever or wild or zany?" (www.codeproject.com)

Ouch, I hate that article-model of CodeProject. It is like they are forcing me to answer a stupid question like in those tests in high-school. Well, yes! I did learn something interesting - Win2K does not support IPv6 by default! And yes, I did learn something fun - I love SQLite! And another yes - the annoying thing is other people's memory leaks... :-)

Just kiddin', CodeProject, I love ya'!

TODO:

  1. In the connections list, show connected username and open DB (if any is open).
  2. Allow to define DB aliases instead of using file paths (two different modes...).
  3. Enhance security: Add encryption for all communication. (Allow client to request encrypted/non-encrypted communication, and server to force encryption or configure the default mode).
  4. Allow client to request DBs' aliases available. (If the client has permission to request so, and if we are not in direct filenames mode.)
  5. Find the time to actually do these "TODO"s!

History

  • 21/01/2008:

    Now the server demo application is much more than a demo!

    • You can run it as a service...
    • It works as a tray icon.
    • It accepts command line arguments in case you do not want it as an NT Service...
  • 23/01/2008:
    • Server app: Fixed a bug with reading the passwords from the INI...
    • Server app: Now determines correctly when a client has disconnected.
    • Server app: Now lists the connected clients and allows you to kill them one-by-one! :-P

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionLooking for a Dot Net version of this Pin
supersystems7-Dec-23 0:53
supersystems7-Dec-23 0:53 
QuestionBug found Pin
szomi22-Dec-13 6:20
szomi22-Dec-13 6:20 
SuggestionNew version, wellcome :) Pin
infal29-Dec-11 0:22
infal29-Dec-11 0:22 
Hi Daniel,

as you can assume, I not only try this version, but extend your work excessively and make a lot of improvements.

Moreover, I have done the work in some "proxy" way - together there are two proxies implemented - direct proxy (using sqlite3* handle directly) and network proxy (using the server over the network).

Why I done it this way? Because we use already some CPP-Wrapper, see here: CppSQLite - C++ Wrapper for SQLite[^].

But this wrapper internally use sqlite3* handles. So I rewrite this one, so they can use a proxy interface instead of. This is a big difference and root of the magic - now we can use the DB CPP Wrapper as is, without a limitation of where database is - local or on server. Latelly it should be an easy work to implement other proxies like a multitargeting proxy, which means a proxy is connected internally to more than one network or direct proxies and is ready to broadcast the data to more than one server. Smile | :)

But back to the root.

The improved server version is not used directly sqlite3* handles anymore - this uses the direct proxy or multiple direct proxies. Wink | ;) This is the root of a freedom. The server can work in several ways (there are just one or two more startup parameters) and use one direct proxy or multiple direct proxies one per connection. And the proxies can open a sqlite3 connection itself per instance or use one in a shared way. This works perfectly in multithreaded environment, also for mulithreaded client!!! And there are not much client implementations support this situation Smile | :) More, each thread maintain a single instance of a wrapper, and server works in a shared manner - this makes the code much cleaner and debuggable, and if one instance is crashed, other continue to work perfectly.

The shared server is born - so it's now possible to start a "shared" instance of a server, which means the server got an sqlite3 handle created elseweher besides the server. I've tried to instance triggers on this handle and done notification to calsses outside a server - and works like a charm. Smile | :)

The DB-Server synchronisation is born! Smile | :) So now we can use the shared server not only as data transport layer, we can use this (indirect) as perfect solution for data synchronisation layer!

So for .NET layer - I've already created one very simple in only less of one hour. Smile | :) I've don't really a nedd this one, but for testing I use express edition and express edition of C++ does not allow me to fast create a GUI application, but C# express allows - so it' was much faster to create an .NET-Wrapper and use this one with C# as to make GUI with C++ express edition! Smile | :)

Do you like to rewrite this work again? Or may be it's better solution to get all works and power together and create an joint work which should be latter a maintained as part on SQLite3.org directly? I can post here my improvements, but for code sharing I mus got a permission from my firm. But for me it's certainly to share my improvements if I use shared works from other people.

The idea is the same as for other publicity common works - it works just better and make a life simpler Smile | :)

Bye,
Alex
GeneralRe: New version, wellcome :) Pin
woj11719-Jan-12 5:56
woj11719-Jan-12 5:56 
GeneralRe: New version, wellcome :) Pin
Nicolas Mohamed1-Feb-12 1:54
Nicolas Mohamed1-Feb-12 1:54 
GeneralRe: New version, wellcome :) Pin
singwg4-Feb-12 14:26
singwg4-Feb-12 14:26 
GeneralRe: New version, wellcome :) Pin
singwg9-May-12 17:21
singwg9-May-12 17:21 
GeneralRe: New version, wellcome :) Pin
singwg22-Jul-12 3:12
singwg22-Jul-12 3:12 
GeneralRe: New version, wellcome :) Pin
Daniel Cohen Gindi22-Jul-12 3:40
Daniel Cohen Gindi22-Jul-12 3:40 
GeneralRe: New version, wellcome :) Pin
singwg22-Jul-12 18:41
singwg22-Jul-12 18:41 
GeneralRe: New version, wellcome :) Pin
hullihulli16-Apr-13 3:14
hullihulli16-Apr-13 3:14 
GeneralRe: New version, wellcome :) Pin
isohelpline22-Jan-18 0:30
isohelpline22-Jan-18 0:30 
BugRevised version of ThreadProc Pin
infal28-Dec-11 13:04
infal28-Dec-11 13:04 
GeneralRe: Revised version of ThreadProc Pin
Daniel Cohen Gindi28-Dec-11 19:46
Daniel Cohen Gindi28-Dec-11 19:46 
GeneralRe: Revised version of ThreadProc Pin
isohelpline22-Jan-18 0:29
isohelpline22-Jan-18 0:29 
BugOther bug's in code and thread termination Pin
infal27-Dec-11 12:57
infal27-Dec-11 12:57 
GeneralRe: Other bug's in code and thread termination Pin
Daniel Cohen Gindi28-Dec-11 19:43
Daniel Cohen Gindi28-Dec-11 19:43 
BugSome Improvements! Daniel, how I can contact you? Pin
infal25-Dec-11 11:57
infal25-Dec-11 11:57 
GeneralRe: Some Improvements! Daniel, how I can contact you? Pin
Daniel Cohen Gindi28-Dec-11 19:42
Daniel Cohen Gindi28-Dec-11 19:42 
GeneralThanks Pin
Jerry Evans13-Jul-10 5:02
Jerry Evans13-Jul-10 5:02 
GeneralSQL Server Compact Edition Pin
Håkan Nilsson (k)11-Mar-10 20:38
Håkan Nilsson (k)11-Mar-10 20:38 
GeneralYou showed very nice example of using SQLite Pin
Khusniddin28-Feb-10 4:40
Khusniddin28-Feb-10 4:40 
Generalbug when transmission packet is fragmented Pin
nearperfect15-Jan-10 11:07
nearperfect15-Jan-10 11:07 
GeneralRe: bug when transmission packet is fragmented Pin
Daniel Cohen Gindi16-Jan-10 9:34
Daniel Cohen Gindi16-Jan-10 9:34 
GeneralClient Lib not working On Windows CE Pin
Cüneyt ELÝBOL11-Apr-08 22:07
Cüneyt ELÝBOL11-Apr-08 22:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.