姚明,81年,97年开始接触电脑,6年的编程学习经历, 曾有4年工作经验,最终转向基础理论学习和研究, 现华中理工科技大学在读,有志于图形学领域工作发展

EMAIL:alanvincentmail@gmail.com QQ:31547735

随笔分类(34)

文章分类(99)

相册

收藏夹(6)

编程技术网站

出国留学网站

数学资源网站

图形学网站

英语资源网站

自由职业者

搜索

  •  

最新评论

[ 原创文档 本文适合高级读者 已阅读19451次 ]  

大型作业答辩:C/S考试系统程序制作详解


作者:姚明

下载源代码


程序组成结构

一、服务器程序

  1. 采用了WinSocket32的完成端口模型(I/O completion ports)
  2. WIN32多线程技术
  3. ODBC APIS 进行数据库操作
二、客户端程序

用Win32 API函数构造主窗体和界面元素,如图一所示:


图一 程序组织结构

服务器程序详解

一、完全端口模型(I/O completion ports)是迄今为止最为复杂的一种I/O模型,假如一个程序需要管理为数众多的套接字,那么采用这种模型往往可以达到最佳的系统性能,不幸的是该模型只适用与WIN2000和WINNT操作系统,因其设计的复杂性,只有在你的应用程序需要同时管理数百乃至上千个套接字的时候,而且希望随着系统内安装的CPU的数量增多,应用程序的性能也可以线性的提升,才考虑采用“完成端口模型”(WEB服务器便是这方面的典型例子)。I/O completion ports是唯一适用于高负载服务器的一个技术,它利用一些线程帮助平衡“I/O请求”所引起的负载,这样的构架特别适合应用在SMP系统中产生所谓的“Scalable”服务器,(Scalable是指能够籍着增加RAM或磁盘空间,CPU个数而提升应用程序效能的一种系统)。

二、完全端口模型的具体实现
  为了使用“完成端口模型”,我产生了一堆线程在端口上等待,线程数量=CPU个数x2+2,我将每个客户端产生的文件句柄与I/O completion ports端口相关联,建立了这种关系之后,任何客户端发出操作请求,便会导致I/O completion packet被送到“完成端口”去,这个步骤是操作系统完成的,为了回应I/O completion packet,我让I/O completion释放一个等待中的线程,如果目前没有线程正在等待,它不会为这个客户端N产生新的线程, 当作用中的线程处理完相应客户端的“overlapped I/O”后,将返回I/O completion端口进行等待,客户端N这时才能够被处理,这样就保证了我的Workers线程总是保持一个稳定的数量(CPU个数x2+2)。如图二所示:


图二 完全端口线程模型示意图

三、数据库的操作实现
  这部分功能主要是通过WinSocket32 API和ODBC API结合使用来实现的,服务端进入监听状态后,为每个客户端提供相应线程处理发过来的指令,通过分析指令,作出以下相应的操作:
客户端发送的指令(自定义的):
      login: 登陆校验 参数:用户名,科目,密码
            Srecv:ScanTm: 检查服务器时间校对试卷修改试卷状态,抛出计数值
            Srecv:GetSta: 获取试卷状态
            Srecv:GetRlt: 获取上次做答
            Srecv:GetNum: 获得试卷相关信息(总题数,开考时间,结束时间)
            Srecv:GetQue: 获取试卷题目内容.
            Srecv:SaveDt: 保存试卷
            Srecv:ChanST: 修改试卷状态.      
四、服务器程序总结
  数据库被单独存放在一个服务器中可以保证数据安全性,程序会将客户端的一切操作显示在窗口中,用户可以通过观察窗口,知道所有客户端的动作。这个程序采用“完成端口”模型,可以满足大规模的考试需求。

客户端程序详解
一、窗口完全采用Win32API函数生成
主要包含一下标准控件:
      static控件
            Edit控件
            Button控件
            Scroll控件
            窗口元素全部采用计算后的相对坐标定位,所以800X600和1024X768下均能正常显示,      
二、试卷的初始化
  考虑到每张试卷的题目数量都不同,为了节约内存空间,所以我在堆中动态生成了一个试卷结构体,通过向服务器程序发送GetNum:指令来获得试卷总题数QuestionNum,然后使用TestPaper=new TestRubric [QuestionNum]
/*结构体定义*/
            //试卷每道题的结构
            struct Questions{
            BOOL state;
            char Text [512];
            };
            struct SelectObject{
            BOOL state;
            char Text[256];
            };
            struct TestRubric{
            struct Questions Tile;
            struct SelectObject choose [4];
            };
            
由于TextOut函数不支持自动换行,所以换行操作必须由我自己完成.因此我用同样的方法在堆中创建了一个Screen用作屏幕显示的结构体
Screen=new  Lines[LINES]
            struct Lines{
            int earmark; //用来存储Button的ID
            BOOL color1;//置颜色标志
            BOOL color2;//置颜色标志
            char Line [512];
            };      
LINES=扫描TestPaper中超过屏幕宽度的行数+ QuestionNum*5+QuestionNum*3
屏幕宽度=客户区的宽/每个文字的宽度/2*2
屏幕高度=客户区的高/每个文字的高度
为每一体产生4个互斥的按钮
按钮总数= QuestionNum*4
在堆中生成hWndList数组保存按钮handle
hWndList=new hWnd [QuestionNum*4]
按钮ID=题号*10+选项号
Screen.earmark=按钮ID


图三

  将TestPaper中的内容经过换行处理之后Copy到Screen结构中,并设置好Screen.earmark,Screen.Color1, Screen.Color2。在主窗口消息循环的WM_PAINT消息中将Screen.Line显示在窗口中:
      TextOut(hdc,x,cyhar*i,Screen.Line,strlen(Screen.Line));      
并检查Screen.earmark中是否为零,不为零就:
      ShowWindow(hWndList[Sreen.earmark/10-1] [Screen.earmark%10-1],1);      

Screen.Color1, Screen.Color2是否为1,如果为1,则改变颜色显示。

三、换行中存在的问题
行宽=客户区的象素宽/每个文字的宽度/2*2是偶数;
汉字占用双字节,字母和标点符号占用单字节;
一行文字=字母+标点+汉字 (有可能产生奇数宽);
当一行文字产生一个奇数宽,最后一个字符又是汉字的时,就会把这个汉字切成两份,另一半会在下一行中显示,这就造成了乱码;
  我的解决办法是在换行时增加一个变量HanChar=0,当扫描到字母或是标点时,就HanChar++。一行文字扫描完后需要另起一行时,判断HanChar的奇偶性,当为奇数时行宽往里缩进一个字节,以避免以上情况。

四、客户端程序总结
  由于客户端界面采用大量计算,显示的内容不会是固定的模式,他会根据题目的长短变化作出相应调整,以达到最好的显示效果。
  当用户登陆验证成功之后,服务器会抛一个时间计数,客户端通过一个定时器,每隔1秒钟将计数减1,并显示倒计时在界面上,直到计数为0,表明考试结束,程序自动保存数据退出。这样做的好处是用户更改客户端的时间,不会影响程序的正常计时。
  客户端每隔10秒钟自动保存一次数据,以防突然死机之类的情况,死机后再次登陆,程序会自动加载你先前保存的作答。但点击“提交试卷”后就无法登陆了。

对例子程序的说明
随付的程序和源码是我大型作业的作品,运行时先运行服务器程序,再运行服务端程序.

  


帐号:姚明
密码:1981922

运行之前请先调整数据库的试卷信息表的开考时间和结束时间。还要确保学生试卷成绩表里面“姚明”那一行中试卷状态为1。

 作者信息
姚明/Ym
邮箱:yaomingmail@sina.com
QQ:31547735
另外我不会打篮球 :-)

[代码性质] VC完整应用程序代码
[代码作者] 姚明/Ym
[文件大小] 162K
[更新日期] 2004-1-17 19:43:00
[下载次数] 13112 下载

(END)

posted on 2007-10-26 00:43 姚明 阅读(1574) 评论(3)  编辑 收藏 引用 所属分类: Win32API

FeedBack:
# re: C/S模式考试程序制作详解 2007-10-26 10:04 万连文
记得在大三的时候,轰轰烈烈的搞“产学研”,我也参加了这个咚咚,socket+ADO+MFC。现在几乎都忘记什么样的了,但是可以肯定的是没有你这么细致。一共好几人,可是写代码的.......。项目的400大洋,在结束之后就不知被谁领走。真TMD有意思,当时就是一个怕,怕数据库连接坏了,怕界面复杂操纵不了,怕....。当然,做的好的,不仅仅是只有选择题,判断、问答、实验等等,就需要结合word、图片、图形绘制了,很复杂的。这样看来,用web的优势就大了。  回复  更多评论
  
# re: C/S模式考试程序制作详解 2007-10-27 17:29 姚明
@万连文
VC做订单没优势,很大的原因就是它的界面开发速度慢,成本高!
VC做产品非常合适,特别是游戏或者大型行业应用软件!

不过,不论怎样,我已经感觉不到编程的创造力,很多情况下,我都是把别人的代码改改然后拿来用,如果没有现成代码,我就必须收集大量相关资料,大部分时间是阅读代码和查看资料,这个过程,我觉得没有任何乐趣!
我思考我编程的初衷是怎样的,现在的状况似乎已经脱离了当初的想法,思考的结果,我发现编程只是一个工具,我平时看的资料只是这个工具的使用说明书,真正的有创造性的工作是工具应用的领域或者如何制造更好的工具的问题上,做个比方,这个关系就像天文望远镜和天文学的关系,计算机就像数学领域的天文望远镜,工具而已,编程也就是使用这些工具的方法,使用工具能需要什么创造力?天文望远镜的使用需要用大量的时间和精力研究吗?会用就够了,我应该把精力放在天文学上或者如何制造看得更远更清晰的天文望远镜上!当然,这和每个人最终的目标不同,天文望远镜,也需要人来操纵不是,不能都去研究天文学和制造天文望远镜,没人提供观察资料啊!呵呵  回复  更多评论
  
# re: C/S模式考试程序制作详解 2007-11-03 12:19 Timothy
以前在vckbase看到过你这篇文章。
不错,很详细的。  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理