SQLite 服务器/客户端实现






4.93/5 (30投票s)
为强大的 SQLite 实现服务器/客户端架构!
引言 / 背景
最近,我不得不为我正在进行的一个大项目选择 SQL Server,说实话——我不喜欢我的选择。首先,网上有很多关于“x 与 y”的性能测试,这些测试对 MS-SQL Server 的评价并不高(更不用说成本和那个庞然大物的资源消耗了),还有 MySQL、PostGRE 等等,但没有一个让我满意。我想要的是一种能够让我精确选择服务器所需功能的东西,使用像 SQLite 一样优秀的数据库引擎……而且免费。
这意味着——我必须自己写一个……
我开始在网上搜索,只有一个认真的结果,那就是 Alex K. 的项目,我记得是 2004 年的(他的项目可以在 这里找到)。
我得到了他使用他代码的许可(实际上,我在发这篇帖子之前刚刚问过他……),我采用了一些他的代码,并写了很多新代码。对于熟悉他代码的人来说,一些函数名可能听起来很熟悉。
总之,他的代码有四个主要问题,我不太喜欢:
- 他通过网络传递句柄(!)。
- 他每次都编译语句并执行。
- 他实际上是封装了 SQLite 2 而不是 SQLite 3……
- VC2005 在线程中发现了内存泄漏!!!
第 1 点的问题很明显,客户端和服务器之间的通信必须是透明的,不能有句柄之类的东西。第 2 点的问题是它会产生过多的开销。你应该执行一个 SQL 查询,一次性获取结果,就这样!(无论如何,这是我的看法……)第 3 点的问题是,大多数人,尤其是我的,喜欢在 SQLite 引擎有更新时更新它,更新内容大意是“修复了一个小 bug”。第 4 点的问题是……嗯,我不知道……你喜欢内存泄漏吗?
基本上,我做的是这样:
我拿了套接字处理函数,稍微调整了一下,并将 gethostbyname
替换为 getaddrinfo
,以便支持 IPv6。IPv4 基本上已经被淘汰了。我重写了线程处理类,保持了相同的架构,只是在一些地方有所不同,但我必须确保没有内存泄漏。堆栈类几乎没有动;我为它们做的主要改变是命名……我还**重写**了 handler 类,保持了相同的基本架构甚至函数名。另外,增加了对 SQL 执行和 SELECT
查询的支持! :-)
在客户端,我添加了一个接口,这个接口完全是我从我的 SQLite 包装类中 übernommen的,所以你不必解析表的结果并从 UTF8 转换……它为你做了一切。还有一件事很重要——我为服务器增加了用户身份验证支持。
好吧,我不会真的告诉你我写了多少代码,所以你只能下载自己看了。我也不打算在这里写任何文档!我没时间。而且,代码本身基本上是自解释的。
注意:如果你计划为 Win2K/Me/98/95 编译,你将不得不包含 wspiapi.h,因为我使用了 getaddrinfo
。看起来在 WinXP 之前,IPv6 还没有成为标准,正如 MSDN 上的 MSDN 所述。
附注——如果有人足够认真,想将这个 SQLite 服务器/客户端项目继续发展下去,请随意。最好将其发布到 SourceForge 之类的地方,以便跟踪进度、文档等……我只是没时间……
使用代码
在编写库的同时,我不得不写一个演示应用程序来测试它们……所以它们与解决方案一起附带。解决方案基本上包括:服务器类、客户端类、服务器应用程序和客户端测试应用程序。如果你想使用这些代码,只需包含相关的库即可。另外,要编译服务器库,你必须包含 SQLite3 库/DLL/源代码,可以从 这里 获取。(预计 sqlite3.h 文件位于子文件夹 ./SQLite/ 中。)
更新 2008/01/21:现在 ZIP 文件也附带 SQLite3 源代码了,因为似乎很多用户不知道如何访问 SQLite 网站,下载源代码并将其包含在项目中……我的意思是,各位!你们不能那样做,但你们可以使用 SQL???
关于安全部分:服务器库的默认模式是不需要身份验证的。除非你编写一个身份验证类并将其附加到服务器。我所做的是编写一个接口类,你应该继承它。在服务器演示应用程序中,我创建了一个名为 CINIAuth
的类,它管理 INI 文件中的用户/密码/权限。当然,这不是最安全的方式,但如果你需要更高的安全性,你可以轻松编写一个加密密码并将其存储在任何你喜欢的地方的类。(天哪!甚至可以存储在 SQLite 数据库中!)
更新 2008/01/21:服务器现在使用 SHA512 加密密码!
更新 2008/01/21:现在,服务器可以作为服务运行。它作为一个托盘图标工作,并接受命令行参数。
参数
- /instsvc - 作为服务安装。
- /remsvc - 卸载服务。
- /minimize - 启动时最小化到托盘。
- /start - 启动时开始监听。
- /port:[port_num] - 设置服务器监听端口为 [port_num]。(不会将此端口保存到 settings.ini。)
- /? 或 /help - 此消息。
在我看来,现在你所要做的就是看看代码,然后试试……所以,去吧!
关注点
“在编写代码时,你学到了什么有趣/好玩/恼人的东西吗?你做了什么特别聪明、疯狂或异想天开的事情吗?”(www.codeproject.com)
哎哟,我讨厌 CodeProject 的这种文章模式。这就像他们强迫我在高中考试时回答一个愚蠢的问题。是的!我确实学到了一些有趣的东西——Win2K 默认不支持 IPv6!是的,我也学到了一些好玩的东西——我爱 SQLite!还有,恼人的东西是别人的内存泄漏……:-)
开玩笑的,CodeProject,我爱你们!
待办事项
- 在连接列表中,显示已连接的用户名和打开的数据库(如果已打开)。
- 允许定义数据库别名而不是使用文件路径(两种不同的模式……)。
- 增强安全性:为所有通信添加加密。(允许客户端请求加密/非加密通信,服务器强制加密或配置默认模式)。
- 允许客户端请求可用的数据库别名。(如果客户端有权限如此请求,并且我们不在直接文件名模式下。)
- 花时间真正实现这些“TODO”!
历史
- 21/01/2008:
现在服务器演示应用程序的功能远不止是演示了!
- 你可以将其作为服务运行……
- 它作为一个托盘图标工作。
- 它接受命令行参数,以防你不想将其作为 NT 服务运行……
- 23/01/2008:
- 服务器应用程序:修复了从 INI 读取密码的错误……
- 服务器应用程序:现在能正确确定客户端何时断开连接。
- 服务器应用程序:现在列出已连接的客户端并允许你逐个杀死它们!:-P