当前位置:文档之家› 题库管理系统设计文档

题库管理系统设计文档

(此文档为word格式,下载后您可任意编辑修改!)华南农业大学软件开发技术实践课程设计实验报告小组成员:教师:林毅申提交日期: 2013年11月30日华南农业大学信息学院课程设计1、基本信息1.1 小组基本信息1.2 项目基本信息这次我们小组开发的是一个面向一所大学内的任课老师以及在校学生的题库管理系统。

作为数字化校园的一部分,该系统的主要的功能包括为教师用户提供的查阅题库,新组试卷功能和面向学生的在线考试功能。

题库分为两部分,一部分是之前教师利用组卷功能得到并保存的试卷,一部分是不同类型的题目。

题目范围为学校内各门课程期末考试的试题,包括公共基础课以及各学院开设的不同课程。

题目不仅包括普通的文字类题目,还包括一些包含复杂元素如图片,特殊公式等的题目,做到基本兼容现在学校内能看到的题目。

考虑到小组成员的技术水平以及项目的实际需要,该系统是采用C/S模式。

为提高效能,服务器方面采用IOCP模型,客户端采用WPF技术来改善Winform在界面上的劣势。

1.3 项目技术信息2、系统架构图注:实线表示数据传输方向,虚线表示模块间调用关系,由被调用者指向调用者服务器程序:数据加密模块:采用一种加密算法,(具体哪种算法等系统实现时,再进行确定),将即将发送的数据进行加密。

保证数据再传输过程中的安全性。

与客户端中的数据加密模块原理一样。

数据解密模块:采用与加密算法相对应的解密算法,将接受到数据,进行解密,还原得到原始的数据。

与客户端中的数据解密模块原理一样。

消息队列:为了能实现同时让尽量多的客户连接到服务器,所以不使用一线程处理一客户模型的服务器。

这里的消息队列是将所有用户对服务器的各种请求按照先进先出的规则排列起来。

等待处理。

如果实现是使用windows io完成端口和对应的SOCKET进行绑定,这个消息队列是由系统生成和维护的。

工作者线程池:线程池用于维护和管理服务器中所有以工作者身份存在的线程,工作者线程就是用来处理客户请求的线程。

线程池的线程会互斥的到消息队列中取出对应的客户请求进行处理。

没有请求时候,所有线程都处于阻塞状态等待消息队列中出现客户请求。

当工作者线程获得客户请求的时候会按顺序去调用数据解密模块,数据传输格式解析模块,业务逻辑处理模块,加密发送数据模块。

数据传输格式解析模块:数据在网络传输的过程中,我们给它规定特定的格式。

通过该模块,服务器可以清楚的知道,客户需要服务器为他实现哪些功能。

但是这里解析的数据需要通过解密之后,才能解析。

对应的客户端想要与服务器进行交互,就需要使用这个特定的格式发送数据。

业务逻辑处理模块:这个模块就是服务器具体工作的模块,模块中包含服务器能够为客户端提供的所有服务。

工作者线程通过解析数据格式,知道客户的需求,再从这个模块中调用指定的服务。

这个模块也是直接和数据库进行交互的模块。

数据发送加密模块:业务逻辑模块处理完客户的请求的服务之后,需要为客户返回处理后的结果。

可能是简单的操作成功和失败的返回结果,也可能是直接数据的传输。

和加密模块结合在一起,说明数据发送前需要进行加密。

数据库模块:采用sql server做数据库管理,技术实现面向业务层的接口。

3、系统功能客户端:学生:在这个题库管理中心中,我们设定的学生功能有查看试卷、导出试卷和在线考试并评分。

查看试卷:学生可以查看不同科目的试卷,选择科目时需要先选择科目分类、学院等上级目录,试卷包括历年考试卷和各学科老师自己组合试题的模拟卷。

导出试卷:学生查看了试卷之后如果需要带出,可以选择导出试卷,导出的试卷根据学生选择存储位置以WORD文档存储。

老师:老师可以使用的功能包括:查看题目、组卷。

组卷分为按要求自动组卷和手动组卷两个部分。

查看题目:跟学生的一样,首先选择科目分类、学院等目录,选择了科目之后还需要选择章节和知识点、或者选择某一套题(具体的操作在编码时确定),进入单个题目可以看到题目分类、难易度、内容和答案,还可以把该题目加入到组卷区里(类似网络购物加入购物车的形式)。

组卷:自动组卷:老师选择科目、难易度,填入试卷总分和考试时间,选择题数目和选择题总分,填空题数目和填空题总分,客观题视科目需要而定,可以选择简答题、计算题、材料分析题等题型,最后各题总分要跟试卷总分相同,全部填写好之后就可以进行自动组卷,组卷成功之后老师看是否满意,不满意可以重来或者可以留下某一些需要的题其他题目随机加入。

数据传输:用户进行操作需要读取数据的时候发出命令传给服务器,服务器传过来的数据接受后给用户看。

服务器:提取数据:根据客户端传来的命令来进行数据库的读取,读取后给传输模块。

数据传输:数据提取出来之后,经过格式化以后再进行加密,之后就可以传输给客户端进行解密并呈现给用户。

4、数据库设计PDM图数据字典清单表名:QB_ACCOUNTS 解释:用户信息表表名:QB_CHAPTERS 解释:章节信息表表名:QB_COLLEGES 解释:学院信息表表名:QB_COURSES 解释:课程信息表表名:QB_ORIGIN 解释:题目来源表表名:QB_PAPERS 解释:试题信息表表名:QB_POINTS 解释:知识点信息表表名:QB_PUBLICKINDS 解释:公共课信息表表名:QB_QUESTIONS 解释:题目信息表表名:QB_STUDENTS 解释:学生信息表表名:QB_TEACHERS 解释:教师信息表5、程序结构整个系统的数据流大致如上图。

用户在客户端上进行操作时,某些需要用到数据库里的数据的操作,客户端就会编写对应的命令编号以及相应的参数,转换成字节流,经过加密发送到服务器。

服务器收到之后经过解密,并且转换回字符串,可以得到相应的命令和参数,根据这个可以进行对应的操作,操作之后返回的是一个布尔值的字符串或者整型数组、字符串数组、题目数组,转换为字节流之后发送给客户端,跟服务器一样接收之后解密转换得到原有的数组或字符串,再分别绑定到对应的控件上。

这是一次完整的客户端和服务器之间的数据传输。

Client:客户端类,与服务器传输的代码。

Parse:服务器返回的数据的转换。

Paper:试卷的类。

Questios:题目的类,里面有选择题、填空题、简答题继承题目类。

SecuritySystem:加密解密。

Download:下载文件,利用Tomcat进行传输。

Login:登录Page。

MainWindow:主界面,Grid加载Login。

SelectCourse:选择科目的Page。

Look:查看题目或试卷的Page。

AutoPaper:自动组卷的窗口。

QLMain、QLMainStu:老师、学生的界面,加载科目和查看的Page。

Detail:题目详情窗口。

PaperDetailxaml:试卷详情窗口。

BufferManager:缓冲区管理器。

SecuritySystem:加密解密。

Paper:试卷的类。

Questios:题目的类,里面有选择题、填空题、简答题继承题目类。

Parser:客户端发送的数据的转换。

Server:服务器类,与服务器传输的代码。

Function:跟数据库打交道,利用SQL语句取数据。

Database:数据库打开、链接等基本操作。

SocketAsyncEventArgsPool:管理栈。

AsyncUserToken:记录客户端信息的类。

Program:程序入口。

6、关键功能及代码实现6.1多并发量的实现为了实现尽量多的并发量,一般不会使用阻塞的socket模型去编写服务器。

因为阻塞的socket操作,需要大量的线程,才能让每个客户都能及时的得到响应,因此cpu在进行频繁的线程切换的过程就浪费了不少cpu的资源。

所以必须要选择一个异步的socket模型,在windows中,IOCP(完成端口)是最适合用来实现网络服务器的,所以就选择IOCP。

在.net的平台中MSDN中对SocketAsyncEventArgs 的描述是:”SocketAsyncEventArgs 类就是这一组增强功能的一部分。

该类专为需要高性能的网络服务器应用程序而设计。

应用程序可以完全使用增强的异步模式,也可以仅仅在目标热点区域(例如,在接收大量数据时)使用此模式。

”所以这次实现选择了SocketAsyncEventArgs 类来实现服务器。

具体会有以下几个方面的实现6.1.1 实现 SocketAsyncEventArgsPool (SocketAsyncEventArgs 对象池)这个对象池用于存放SocketAsyncEventArgs 对象。

对象池中的对象都是预先分配的,而且也是可重用的,当有客户连接的时候,就在对象池中给客户取出一个对象使用。

当客户退出时就回收客户使用的SocketAsyncEventArgs 对象,放回对象池当中,使用这个对象池的好处是在服务器运行阶段,减少了对象申请释放的操作。

对于多客户的连接中,就需要多次分配。

也为服务器运行的过程节省一些cpu时间。

主要代码如下,简单的实现对象池的效果,实际上就是用栈来管理对象using System;using System.Collections.Generic;using System.Linq;using System.Text;using .Sockets;namespace Server_{class SocketAsyncEventArgsPool{// SocketAsyncEventArgs 管理栈private Stack<SocketAsyncEventArgs> pool_;public SocketAsyncEventArgsPool(int capacity){pool_ = new Stack<SocketAsyncEventArgs>(capacity);}// 回收没用的SocketAsyncEventArgspublic void Push(SocketAsyncEventArgs item){if (item == null){throw new ArgumentNullException("Items added to a SocketAsyncEventArgsPool cannot be null");}lock (pool_){pool_.Push(item);}}// 分配SocketAsyncEventArgspublic SocketAsyncEventArgs Pop(){lock (pool_){return pool_.Pop();}}// 返回可用SocketAsyncEventArgs的个数public int Count{get { return pool_.Count; }}}}6.1.2 实现缓冲区管理(BufferManager类)自定义的一个类,因为在每一个SocketAsyncEventArgs对象中,都必须为其指定一个缓冲区。

相关主题