Kanagawa的资源

  • 基于SOA的分布式水果商店系统

    一、项目介绍1.1 项目简介基于SOA的分布式电商客户端系统,各服务和总线之间采soap1.2协议。

    1.2 采用关键技术
    CXF3.7框架
    Spring
    JSP&Servlet
    JSTL
    EL表达式
    c3p0连接池
    DbUtils数据访问框架
    BeanUtils
    jQuery
    Ajax
    自定义事务管理机制MannagerThreadLocal
    SOAP1.2协议

    1.3 开发环境
    jdk1.7
    tomcat8.5、8.0
    MySql5.5.27
    MyEclipse Enterprise Workbench 2017 CI 7
    字符集编码:utf-8

    1.4 项目演示主页


    登录




    注册

    购物车


    水果列表


    历史订单

    二、源码简析2.1 架构设计


    ws-fruitshop-bus
    总线




    ws-fruitshop-fruit
    提供水果服务


    ws-fruitshop-order
    提供订单服务


    ws-fruitshop-user
    提供用户服务




    2.2 接口描述


    服务接口
    方法
    描述
    发布地址
    Wsdl文件




    UserServiceInterface
    login()
    为总线提供登录服务
    http://127.0.0.1:8081/ws-fruitshop-user/ws
    UserServiceInterface_wsdl.xml


    UserServiceInterface
    regist()
    为总线提供注册服务
    http://127.0.0.1:8081/ws-fruitshop-user/ws
    UserServiceInterface_wsdl.xml


    FruitServiceIntergface
    findFruitPage()
    为总线提供水果页服务
    http://127.0.0.1:8084/ws-fruitshop-fruit/ws
    FruitServiceInterface_wsdl.xml


    FruitServiceIntergface
    findFruitById()
    为总线提供查询水果服务
    http://127.0.0.1:8084/ws-fruitshop-fruit/ws
    FruitServiceInterface_wsdl.xml


    FruitServiceInterface2
    updateReserve()
    为order服务提供更新水果库存服务
    http://127.0.0.1:8084/ws-fruitshop-fruit/ws
    FruitServiceInterface2_wsdl.xml


    OrderServiceInterface
    findOrderByUserID()
    为总线提供根据用户ID查找订单服务
    http://127.0.0.1:8087/ws-fruitshop-order/ws
    FruitServiceInterface2_wsdl.xml


    OrderServiceInterface
    addOrder()
    为总线提供添加订单服务
    http://127.0.0.1:8087/ws-fruitshop-order/ws
    FruitServiceInterface2_wsdl.xml






    2.3 数据库ws-fruitshop-user项目使用mysql5.5.27

    ws-fruitshop-order项目使用mysql5.5.27

    ws-fruitshop-fruit项目使用mysql5.5.27

    2.4 webservice服务开发
    下载cxf框架,并配置系统环境变量。本次开发使用apache-cxf-3.2.7
    创建web项目,并导入CXF下lib文件夹里的所有jar包
    创建SEI接口,注意加入‘@WebService’标签,如:



    创建SEI实现类,如


    配置spring配置文件applicationContext.xml发布服务,配置服务地址、服务接口和服务实现类。如:


    配置web.xml,配置spring配置文件和加载的listener,配置CXF的servlet


    将项目部署到tomcat下,启动tomcat
    测试服务

    WSDL地址规则
    如:http://localhost:8081/ws-fruitshop-user/ws

    2.5 webservice服务生成客户端并部署
    在客户端项目下引入CXF下lib文件夹里的所有jar包
    使用CXF提供的wsdl2java工具生成客户端代码如:wsdl2java -p com.fruitshop.service.user -d . http://localhost:8081/ws-fruitshop-user/ws/user?wsdl

    = 配置客户端spring配置文件applicationContent.xml


    根据wsdl说明书使用生成代码来调用远程服务

    2.6 服务业务关键代码
    三个服务项目和一个总线项目统一采用MVC风格,包的命名格式类似下图:


    Dao层使用C3P0连接池和Apache.commons.dbutils框架对数据库进行操作



    事务管理,自定义线程管理类ManagerThreadLocal


    使用Apache.commons.beanutils工具封装从前端传入后端的数据


    使用JSTL的<c:forEach >标签水果展示、购物车信息、历史订单信息等都采用了动态表单


    登录、注册、修改信息,使用jQuery在前台拦截可以不访问数据库确认的错误,减少数据库约束。以注册的jQuery为例,提前写好错误提示的div文字,当检测出需要拦截时,jQuery.css()方法响应对应div的id,更改样式

    三、项目部署简介注:因为在本地测试,所有的服务和总线都部署在本地。

    在MyEclipse或Eclipse下打开四个项目
    分别右键每个“工程 -> Properties -> Java Build Path -> Add JARs”导入所有“外部jar包”文件夹下的jar包
    在项目文件中,已经包含了服务所生成的客户端代码。注意生成的客户端代码还是java源码,并没有进行打包处理,已经导进了项目源码中
    向数据库中导入三个数据库脚本fruit.sql、order.sql、user.sql,会生成三个数据库,数据库中已经存在一些开发时测试用的数据
    根据本地数据库信息配置ws-fruitshop-fruit、ws-fruit-order和ws-fruit-user三个服务项目src下的c3p0-config.xml



    准备4个tomcat服务器,先将提供服务的ws-fruitshop-fruit、ws-fruit-user项目部署在相应的两个服务器上
    由于服务项目ws-fruitshop-order和总线ws-fruit-bus都用到了其他服务提供的接口,所以先配置ws-fruitshop-order项目config下的applicationContext.xml的fruit服务地址。只需根据ws-fruitshop-fruit所在服务器的端口号修改端口号即可。配置完成后,将项目ws-fruitshop-order部署在第三个服务器上,并启动



    再配置ws-fruitshop-bus项目config下的applicationContext.xml。根据前三个服务所在服务器的端口号修改端口号即可


    再将ws-fruitshop-bus部署到第四个服务器上并启动访问:localhost:8080/ws-fruitshop-bus/index.jsp。当然端口号还是修改为总线项目部署服务器的端口号
    注意:

    在步骤“3”中讲到,所有服务的客户端代码已经生成,并且以java源代码的形式添加到相应项目的相应包中。当然,可按照该文档“webservice服务生成客户端并部署”进行重新生成。生成之后在替换相应包中的源码即可,所以下面给出各项目用到其他外部服务的客户端代码所放的位置

    在ws-fruitshop-bus中com.fruitshop.fruit.service存放ws-fruitshop-fruit提供的FruitServiceInterface服务。com.fruitshop.order.service存放ws-fruitshop-order提供的OrderServiceInterface服务。com.fruitshop.user.service存放ws-fruitshop-user提供的UserServiceInterface服务在ws-fruitshop-order中com.fruit.service2存放ws-fruitshop-fruit提供的FruitServiceInterface2服务
    各服务提供方的发布地址也是能修改的,例如:http://127.0.0.1:8084/ws-fruitshop-fruit/ws/fruit?wsdl

    ‘127.0.0.1’ 是服务发布的服务器地址‘8084’是服务器发布服务的相应端口号‘ws-fruitshop-fruit’是服务项目名称‘ws’是CXF的servletd的url-pattern,可在WebRoot/WEB-INF/web.xml中修改‘fruit’是服务接口的地址可在config/applicationContext.xml中配置
    1  留言 2021-03-06 10:35:23
  • 基于java swing和oracle的项目管理系统

    1、需求分析1.1 背景项目管理系统,是反映公司员工资料,项目负责部门和项目进度,设备采购软件系统,是管理项目的有效工具。
    面向用户:对项目进度跟踪,公司人员信息管理和设备管理的公司。只能由公司内部查看数据库中的数据。要求使用本系统的用户管理系统的使用有所了解,知道基本的操作和使用过程的注意事项。
    1.2 系统目标系统对外部封闭,不允许外部人员访问公司项目管理系统中的数据库。能够安全的访问系统独立的数据库。程序实现数据库数据的直观显示,保证数据库的能够为公司提供较为方便和基础的项目管理服务,能够为公司管理层提供监督渠道。
    数据分析:员工的基本信息,部门的基本信息,项目的基本信息,设备基本信息
    1.3 功能分析项目管理系统应该能够提供以下功能:管理员登陆、员工信息管理、部门信息管理、项目信息管理、设备信息管理。

    管理员登录:项目管理系统采用Oracle数据库连接的服务名,用户名和口令(密码)验证模式,进入项目管理系统前项目管理员必须在登陆界面输入验证信息方可进入项目管理系统的主界面进行相应的操作
    学生信息管理:学生信息管理包含五个模块:学生信息的浏览、添加、删除、查询、修改
    部门信息管理:包含一个模块:部门经理信息查询
    项目信息管理:包含两个模块:根据项目经理的姓名查询项目的完成情况、查询某个项目的设备购买情况
    设备信息管理:包含三个模块:设备费用查询、设备供应商查询、添加设备

    1.4 性能需求分析
    系统易操作性:项目管理系统应该做到操作简单,界面友好,使得用户可以快速上手使用,不受到专业知识的限制
    系统可维护性:由于系统涉及的信息比较多,数据库中的数据需定期修改,系统可利用的空间及性能也随之下降,为了使系统更好地运转,用户可以对系统数据及一些简单的功能进行独立的维护及调整

    2、概念设计2.1 概念模型(E-R图)
    2.2 数据字典2.2.1 数据字典数据字典包括的项目有数据项、数据结构、数据流、数据存储、加工逻辑和外部实体。可使用一些符号来表示数据结构、数据流和数据存储的组成。
    员工表



    数据元素
    数据类型
    数据长度
    数据描述




    w_id
    VARCHAR2
    4
    员工编号


    w_name
    VARCHAR2
    16
    员工姓名


    sex
    CHAR
    2
    员工性别


    age
    CHAR
    20
    员工年龄


    contract_date
    DATE

    合同日期


    d_id
    VARCHAR2
    4
    部门编号


    d_name
    VARCHAR2
    12
    部门名称


    post
    VARCHAR2
    6
    员工职务



    部门表



    数据元素
    数据类型
    数据长度
    数据描述




    d_id
    VARCHAR2
    4
    部门编号


    d_name
    VARCHAR2
    12
    部门名称


    m_id
    VARCHAR2
    4
    部门经理编号


    m_name
    VARCHAR2
    8
    部门经理姓名


    w_num
    NUMBER

    员工人数



    项目表



    数据元素
    数据类型
    数据长度
    数据描述




    p_id
    VARCHAR2
    4
    项目编号


    p_name
    VARCHAR2
    16
    项目名称


    d_id
    VARCHAR2
    4
    部门名称


    w_id
    VARCHAR2
    4
    项目经理编号


    fund
    FLOAT
    126
    项目经费


    type
    VARCHAR2
    4
    项目类型


    signing_time
    DATE

    签订时间


    complete_time
    DATE

    应完成时间


    check_time
    DATE

    验收时间


    remarks
    VARCHAR2
    8
    备注



    设备表



    数据元素
    数据类型
    数据长度
    数据描述




    e_id
    VARCHAR2
    4
    设备编号


    e_name
    VARCHAR2
    12
    设备名称


    fee
    FLOAT

    设备费用


    supplier
    VARCHAR2
    12
    供应商


    p_id
    VARCHAR2
    4
    项目编号


    remarks
    VARCHAR2
    8
    备注



    2.3 数据流图数据流图(Data Flow Diagram)是一种图形化技术,它描绘信息流和数据从输入到输出的过程中所经受的变换。根据数据流图,可以分析出程序所需的模块和模块之间的调用关系。
    如下图所示,在项目管理系统,在用户界面捕捉用户的操作,接受事务后数据流流向不同的模块。

    2.4 关系数据库设计员工表



    职工号
    姓名
    性别
    年龄
    合同日期
    职务
    部门编号













    项目表



    项目号
    项目名
    合同经费
    类型
    签订时间
    应完成时间
    验收时间
    项目经理编号
    备注















    设备采购表



    项目号
    设备名称
    费用
    供货商
    项目编号
    备注












    部门表



    部门编号
    部门名称
    经理编号









    3、逻辑结构设计3.1 关系描述
    员工与部门的关系:n:1一个员工只能属于一个部门,一个部门可以有多个员工
    部门与项目的关系:1:n一个部门可以负责多个项目,一个项目只能由一个部门负责
    员工与项目的关系:m:n一个员工可以实现多个项目,一个项目可以由多个员工实现
    员工与设备的关系:1:n一个员工可以采购多个设备,一个设备只能由一个员工采购
    项目与设备的关系:1:n一个项目可以使用多个设备,一个设备只能由一个部门使用

    3.2 系统结构图
    3.3 流程图
    4、物理设计存储安排及路径:将数据的稳定性将数据分开存放以提高系统性能,并对数据的存取频率对数据进行分开存放。方法选择:数据库管理系统自动会在每个表的主码上建立索引。在员工表上w_id列上建立PK_WORKER索引,这样可以多次进行对员工查询。同样对部门表,项目表,设备表也有这样的操作。
    4.1 表格的结构员工表



    数据元素
    数据类型
    数据长度
    数据描述




    w_id
    VARCHAR2
    4
    员工编号


    w_name
    VARCHAR2
    16
    员工姓名


    sex
    CHAR
    2
    员工性别


    age
    CHAR
    20
    员工年龄


    contract_date
    DATE

    合同日期


    d_id
    VARCHAR2
    4
    部门编号


    d_name
    VARCHAR2
    12
    部门名称


    post
    VARCHAR2
    6
    员工职务



    部门表



    数据元素
    数据类型
    数据长度
    数据描述




    d_id
    VARCHAR2
    4
    部门编号


    d_name
    VARCHAR2
    12
    部门名称


    m_id
    VARCHAR2
    4
    部门经理编号


    m_name
    VARCHAR2
    8
    部门经理姓名


    w_num
    NUMBER

    员工人数



    项目表



    数据元素
    数据类型
    数据长度
    数据描述




    p_id
    VARCHAR2
    4
    项目编号


    p_name
    VARCHAR2
    16
    项目名称


    d_id
    VARCHAR2
    4
    部门名称


    w_id
    VARCHAR2
    4
    项目经理编号


    fund
    FLOAT
    126
    项目经费


    type
    VARCHAR2
    4
    项目类型


    signing_time
    DATE

    签订时间


    complete_time
    DATE

    应完成时间


    check_time
    DATE

    验收时间


    remarks
    VARCHAR2
    8
    备注



    设备表



    数据元素
    数据类型
    数据长度
    数据描述




    e_id
    VARCHAR2
    4
    设备编号


    e_name
    VARCHAR2
    12
    设备名称


    fee
    FLOAT

    设备费用


    supplier
    VARCHAR2
    12
    供应商


    p_id
    VARCHAR2
    4
    项目编号


    remarks
    VARCHAR2
    8
    备注



    4.2 索引对每个表的主键建立索引:
    CREATE UNIQUE INDEX "CHAN"."PK_WORKER" ON "CHAN"."worker" ("w_id")CREATE UNIQUE INDEX "CHAN"."PK_DEPARTMENT" ON "CHAN"."department" ("d_id")CREATE UNIQUE INDEX "CHAN"."PK_PROJECT" ON "CHAN"."project" ("p_id")CREATE UNIQUE INDEX "CHAN"."PK_EQUIPMENT" ON "CHAN"."equipment" ("e_id") 对project的”p_name”字段表:CREATE INDEX "CHAN"."I_PROJECT_NAME" ON "CHAN"."project" ("p_name")
    4.3 视图部门经理信息视图
    create or REPLACE view v_d_mASselect "worker"."w_id","worker"."w_name","worker"."sex","worker"."age","worker"."contract_ date","worker"."post","department"."d_name"from "worker","department"where "worker"."w_id"="department"."m_id"
    项目完成情况视图
    create or REPLACE view v_m_pASselect "worker"."w_name","project"."p_name","project"."signing_time","project"."complete_time"from "worker","project"where "worker"."w_id"="project"."w_id"
    5、运行维护转储:定期进行静态转储,动态转储,海量转储。
    数据库中可能发生各种各样的故障,大致可以分为以下几类:

    事务故障的恢复策略主要是:反向扫描日志文件,查找该事物的更新操作;对该事物的更新操作执行逆操作;继续反向扫描日志文件,查找该事物的其他更新操作,并做同样处理;如此处理下去,直至读到此事物的开始标记,事物故障恢复就完成了
    系统故障的恢复策略主要是:正向扫描日志文件,找出在故障发生前已经提交的事务,将其事务标识记入重做队列。同时找出故障发生时尚未完成的事务,将其事务标识记入撤消队列;对撤消队列的各个事务进行撤消处理;对重做队列的各个事务进行重做处理
    介质故障的恢复策略主要是:装入最新的数据库后备副本,使数据库恢复到最近一次转储的一致性状态。装入相应的日志文件副本,重做已完成的事物

    6、用户手册本系统基于Java开发,要使用本系统在本机上必须安装有Java开发环境,数据库使用Oracle。
    登录界面
    运行程序之后首先进入登陆界面,在登录界面中输入服务名,用户名(数据库的用户名,比如SCOTT),密码。例如我的数据库的服务名是orcl,用户名是CHAN。经过正确的连接即可进入到程序的主界面:

    主界面
    如下图所示,应用程序界面包括 “切换卡 (用来切换页面)”,“显示区 (显示基本信息)”,“查询区 (用来进行数据查询)”,“控制按钮 (用来进行基本操作)”:

    员工页面
    点击打开表格可以查看所有员工的基本信息,关闭表格可以清空页面上的表格显示:

    点击添加信息可以添加某个员工的信息:

    点击修改可以修改某个员工的信息(注意:员工的编号在数据库中是唯一的,被修改的员工的编号在数据库中必须存在)。

    点击删除信息可以删除某个员工的信息(同样编号必须存在):

    在部门页面可以通过部门名称查询部门经理的信息:


    项目页面

    点击查询完成情况可以查询某项目经理(姓名)完成合同的情况:

    点击查询设备采购可以某个项目设备采购情况:

    在设备页面有一下几个查询:

    7、总结7.1 遇到的问题Oracle数据库与之前接触过的数据库SQL语句有些不一样,除了常用的增删查改与其他主关系型数据库相似,其他的语句还是有一些区别的。在实习中经常因为在SQL语句中少个双引号或者将双引号写成单引号而出错,所以在刚开始写存储过程中用了不少时间。可见Oracle数据库对语法的要求比较严格。
    7.2 存在的问题
    在这次实习中,我发现自己的数据库设计能力还稍有不足,对项目管理系统的几个表的设计不是很合理,表中有些字段的类型和长度可能与实际应用不相符。在进行数据库设计时应该考虑实际项目中的应用,这样才能设计出满足实际需求的数据库管理系统
    客户端程序中的程序设计时没有很好地采用架构来实现。使用三层逻辑架构时没有做到完全的层次分离,在表现层中还存在一些业务逻辑层的代码。数据库中每个表都应该用一个类来封装,然后对类中的成员变量也就是数据库表中的每个字段分别设置set()和get()方法
    程序尚存在一些已知和未知的BUG,反映出自己在程序设计时对问题的考虑不够全面,对于在实际中可能存在的情况没完全把握

    7.3 收获这次实习让我学习了在项目中经常使用到的主流关系型数据库Oracle,掌握Oracle的特征和基本使用方法。在项目中使用Oracle可以实现对SQL语句的封装,不仅提高程序的执行效率还提高了数据的安全性。当对数据库进行复杂操作时(如对多个表进行 Update,Insert,Query,Delete 时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。这些操作,如果用程序来完成,就变成了一条条的 SQL 语句,可能要多次连接数据库。而换成存储,只需要连接一次数据库就可以了。
    2  留言 2020-08-24 15:54:56
  • 基于C#和Access的智能聊天机器人

    一、软件说明1.1 功能说明一个可以自动回复的聊天机器人.
    1.2 解决什么样的实际问题用于娱乐,解闷。
    1.3 性能说明软件还存在一定的BUG,有待改进。
    1.4 程序类型说明娱乐性应用程序。
    二、软件设计2.1 软件整体结构图及模块划分
    软件的结构只有一个聊天界面,分别有输入框,显示聊天信息框,发送按钮和退出按钮,导入词库按钮和调教按钮。
    2.2 在VS的“解决方案资源管理器”中的文件说明
    解决方案中,有5个类,其中:

    ”聊天机器人”类是主类,窗口显示类
    ”DataBase”是连接数据的类,本程序用到的是access数据库
    “Iostreams”类是文件操作类,主要是读取一个txt文件,用于导入词库
    ”Regugar”类是正则表达式品配类,用于品配聊天的问题
    ”Robot”类是一个机器人对象

    Resources文件是用于存放图片文件。
    2.3 各模块对应的主要对象和方法2.3.1 ”聊天机器人”类主要属性
    private Robot A; //机器人对象private string Ask; //发送信息private string Answer; //返回信息private int isTeaching; //调教模式private Point mouseOff; //鼠标移动位置变量private bool leftFlag; //标签是否为左键private string FileName; //txt文件路径private Thread T1; //创建一个线程
    主要方法
    /////发送按扭private void button_sent_Click(object sender, EventArgs e){ ///正常聊天状态 if (isTeaching == 0) { Ask = this.richTextBox_sent.Text; //设置为右对齐 this.richTextBox1_accept.SelectionAlignment = HorizontalAlignment.Right; this.richTextBox1_accept.AppendText(Ask + ":主人 \n"); Answer = A.answer(Ask); //设置为左对齐 this.richTextBox1_accept.SelectionAlignment = HorizontalAlignment.Left; this.richTextBox1_accept.AppendText(" "+ A.name + ":" + Answer + "\n"); } ///////调教机器人状态 else if (isTeaching == 1) { Ask = this.richTextBox_sent.Text; this.richTextBox1_accept.SelectionAlignment = HorizontalAlignment.Right; this.richTextBox1_accept.AppendText(Ask + ":主人 \n"); isTeaching = 2; } else { Answer = this.richTextBox_sent.Text; this.richTextBox1_accept.SelectionAlignment = HorizontalAlignment.Left; this.richTextBox1_accept.AppendText(" "+A.name+":" + Answer + "\n"); A.learn(Ask,Answer); isTeaching = 1; } //自动滚动到插入位置 this.richTextBox1_accept.ScrollToCaret(); //清空发送框 this.richTextBox_sent.Clear();}///导入词库private void Openfile(){ //导入词库 Iostreams.Import(FileName); T1.Abort();}
    2.3.2 ”DataBase”类//根据接收到的字符串返回数据public static List<conversation> search(string sql){ List<conversation> answer = new List<conversation>(); conversation con = null; OleDbConnection conn = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|ChatRobot.mdb"); ///连接数据库 conn.Open(); //执行sql查询 OleDbCommand com = new OleDbCommand(sql, conn); OleDbDataReader reader = com.ExecuteReader(); //读取查询结果 while (reader.Read()) { con = new conversation(reader.GetString(0), reader.GetString(1)); answer.Add(con); } conn.Close(); return answer;}
    2.3.3 “Iostreams”类public static void Import(string File_Name){ using (StreamReader sr = new StreamReader(File_Name, Encoding.Default)) { string line1,line2; //按行读取 while((line1=sr.ReadLine())!= null) { line2 = sr.ReadLine(); DataBase.Insert(line1, line2); sr.ReadLine(); } }}
    2.3.4 ”Regugar”类//正则表达式品配public static bool match(string a, string ask){ //简单的正则表达式 Regex re = new Regex(@"[\s\S]*" + a + @"[\s\S]*"); //品配成功则返回true,否则返回false return re.IsMatch(ask);}
    2.3.5 ”Robot”类//问答函数public string answer(string ask){ List<conversation> answers = new List<conversation>(); string answer=null,a=null; ///sql语句品所有字符的模糊搜索 a = "SELECT ask,answer FROM [chatwords] WHERE (ask LIKE'%[" + ask + "]%') ORDER BY ask DESC"; answers = DataBase.search(a); if (answers.Count != 0) { for (int i = 0; i < answers.Count; i++) { if (Regular.match(answers[i].ask,ask )) return answers[i].answer; } } answer = "听不懂"; //返回包括有输入的任一字的ask和answer return answer;}
    2.4 数据库设计或数据文件说明数据库设计,只创建一个chatwords表,用于储存ask语句和answer语句。

    数据文件.txt文件。问和答不空行,每个问答之间要空一行,必须要按这样的格式才能正确导入词库。

    三、测试测试用例列表地和软件运行截图

    智能聊天机器人的词库是存在数据库中的,当我输入信息如”你好”,点击发送按钮后,程序获取输入信息,然后通过输入信息把据库中包含有输入信息的任一字符的”ask”的所有问答数据找出来,再通过正则表达式,反过来,用查找到的”ask”品配输入信息,一旦品配成功,则返回对应的answer。

    通过penFileDialog按键,打开对话框,默认为打开txt文件。
    四、附录机器人的词库是用酷Q免费提供的词库。
    主要用到的控件有:

    richTextBox
    pictureBox
    Botton
    Label等等
    1  留言 2019-10-20 11:45:30
  • 基于80x86汇编语言的打砖块游戏

    1 目标和意义为了巩固汇编语言与接口技术课程所学的理论知识,理解计算机的基本系统结构,理解处理器的工作过程,探究数据和指令的内部表述,特选择本实验。
    此实验,能训练运用显示器编程的能力和运算操作的能力,训练延时和图形重绘的能力,训练汇编键盘输入控制的能力,训练汇编语言编写函数和函数间调用的能力。同时训练一般游戏的设计能力。
    在此基础上完成具有特定功能的较复杂的汇编语言经典游戏打砖块的设计与编程。
    2 专题实验2.1 选题描述经典游戏打砖块是很多人曾经玩过的经典游戏,也是一段令人难忘的经历。选择这个课题一方面是为了揭开自己曾经难忘的游戏后台,另一方面也是将理论与实践结合极好的机会。
    这个游戏的核心在于砖块和小球的控制,难度适中但有很大的发挥余地,而且需要在汇编语言中不断变换处理焦点,对汇编语言的核心把握要求相对较高,基本上满足了本次专题实验的难度要求。另外,这个游戏的可扩展性很高,突出在自己可以主动或被动的添加各种道具,从而丰富游戏过程,加大设计难度。
    2.2 问题分析
    砖块:易碎砖块、普通砖块、硬质砖块。

    易碎砖块:所有砖块中最容易被打击掉的砖块。默认强度为1,即任何类型的球只需击打一次此类砖块,它都会被打碎普通砖块:默认强度为2。是在普通游戏难度中最多的砖块。普通球需要击打2次方可以击碎此类砖块硬质砖块:默认强度为4。普通球需要击打4次方可以击碎此类砖块。在难度较大的情况下,此类砖块的比例会有所增加
    道具:奖生命、奖分数、大球拍、小球拍、球减速、球加速、普通炸弹、超级炸弹

    奖生命:每个玩家都是有一定的生命值的,如果玩家的生命值为零,那么玩家就结束了当次游戏。如果玩家可以在游戏过程中,接到生命值,玩家的生命值将会加1。对玩家来说,奖生命值是最好的奖励奖励分数:每个玩家在进行游戏时,都会进行一个分数叠加。每当玩家打掉砖块或者接到一定的道具时,玩家的分数就会增加大球拍:这个道具的功能可以使玩家的球拍变大。当玩家接到这个道具时,如果玩家的球拍还未达到最大球拍宽度,那么玩家的球拍将会变宽;如果玩家的球拍已经达到最大的宽度,那么这个道具将不会对玩家的球拍起作用小球拍:这个道具的功能可以使玩家的球拍缩小。当玩家接到这个道具时,如果玩家的球拍还未达到最小球拍宽度,那么玩家的球拍将会变窄;如果玩家的球拍已经是最窄的宽度,那么这个道具将不会对玩家的球拍起作用。因为这个道具对玩家的防守力不利,因此玩家应该尽可能避免接到此道具球减速:这个道具可以减缓玩家的球的速度,玩家最多可以通过两次减速使自己的球的速度降到最低,以此来增加自己的防守力球加速:这个道具可以加速玩家的球的速度。玩家醉倒可以通过两次加速来使自己的球的速度加到最大。对于比较熟练的玩家,这个道具可以快速将砖块打完,但却降低了自己的防守能力普通炸弹:当玩家接到这个道具的时候,当前游戏界面中断最低3层将会被请客。在游戏的设置上,砖块在倒数第三排全部为硬质砖块,因此如果玩家再出现这个道具而没有接到时,玩家将不得不画很长的时间来将倒数第三排的硬质砖块打掉超级炸弹:如果玩家接到这个道具,那么当前屏幕中的所有砖块都会消失,玩家直接完成任务,可以进入下一关
    飘动档板:为了增加游戏的复杂性,在游戏界面的中间处增加了两个飘动档板。它们的生命值为无穷,因此将会一直在游戏的过程中存在。由于飘动档板的存在,使得小球不一定每次都能击到砖块
    球拍变化:球拍的变化主要包括球拍的的加宽和变窄。假设球拍的最初始的宽度为1,那么球拍的最宽宽度可以达到5/3,最窄将会缩窄到2/3。在游戏过程中,玩家可以通过两次累加“大球拍”道具而时球拍加宽到5/3,也可能因为接到“小球拍”道具两次而变为宽度为2/3的球拍

    2.3 实验程序设计游戏进入界面

    游戏过程界面

    在游戏的过程中,主要有以下的键可以用来控制:

    鼠标:对球拍的左右控制
    Space:开始/暂停游戏
    Esc:退出游戏
    R:重新开局
    Y:继续玩

    游戏中的各个过程(函数)
    ;******************************************************************;当接到炸弹后,调用这个函数来实现特效 bomb_show proc near ;函数一;******************************************************************;没什么好解释的吧,很简单的延时 waitf proc near;函数二;******************************************************************;当将所有的砖块都打完后,执行这个函数 cmpgamefun proc near;函数三;******************************************************************;这个函数是当小球死光光了以后调用的 balldeadfun proc near ;函数四;******************************************************************;replayfun这个函数是用来处理当用户按下r或者R时,进行内存数据重新赋值 replayfun proc near ;函数五;******************************************************************;waitfun这个函数是当用户按下空格时,游戏处于暂停状态 waitfun proc near ;函数六;******************************************************************;通过对系统中断向量的重置,可以使得程序以每秒18.2次的速度对小球和砖块进行处理。zhongduan proc near ;函数七;******************************************************************;ballstep这个方法是用来处理小球运动函数 ballstep proc near ;函数八;******************************************************************;getpos这个方法是通过对当前的 球的位置 以及 的运动向量 和球的速度 ;而得到新的 运动向量 和新的位置 ;这个方法是在当前的运动向量的前提下,得到小球的下一个位置。当与墙壁或; 者砖块相撞时,这个方法也要对运动向量进行一定的修改。getpos proc near ;函数九;******************************************************************;这个方法是用来计算小球与砖块的碰撞的,是与哪一个砖块碰撞,它的抗击能力将减一 ;如果为0,则砖块消失,并加分 hitbrick proc near ;函数十;******************************************************************;这个函数是用来处理两个飘动挡板的 wave_brick_fun proc near ;函数十一;******************************************************************;这个方法是用来画道具的,其中道具的左上角的x和y的位置已经存储在propx和propy中 ;另外,道具的颜色也有n种,根据不同的道具,选择不同的颜色 printprop proc near ;函数十二;******************************************************************;setball这个方法是用来画出小球 ;左上角的位置和颜色都在内存中ballx和bally以及color中存储 ;小球的大小是固定不变的 setball proc near ;函数十三;******************************************************************;这个方法是用来填充一个矩形的颜色。其中,矩形的左上角的坐标和右下角 ;坐标以及颜色值存储在内存变量中huaqidianx\huaqidiany\huazhongdianx ;huazhongdiany\color setarea proc near; 函数十四;******************************************************************;这个方法是用来将分数写入屏幕的 score_screen proc near ;函数十五;******************************************************************;这个函数是对道具在屏幕中的运动进行处理的,即道具从上落下,直到落地或者被球拍接住prop_screen proc near ;函数十六;******************************************************************;是用来画出球拍的位置,其中球拍的左端位置以及球拍的宽度由内存记录 mouse_racket proc near ;函数十七;******************************************************************;inmenufun这个函数是进入画面 inmenufun proc near ;函数十八;******************************************************************;init这个方法是在程序开始运行时,画出界面用的 ;每次程序运行或者玩家重新开始时会调用一次 init proc near ;函数十九;******************************************************************;以下的代码是用来发声GENSOUND PROC NEAR ;函数二十MUSIC2 PROC NEAR ;函数二十一
    游戏中的数据段代码(部分)
    ;此处输入数据段代码 ;这些变量是用来给setarea传递参数,函数十四qidianx dw 0 ;起点xqidiany dw 0 ;起点yzhongdianx dw 10 ;终点xzhongdiany dw 3 ;终点ycolor db 10 racket_color db 0111b;球拍颜色—白色frame_color db 0110b;边框颜色—棕色 ball_color db 1110b;球的颜色—黄色brick_color1 db 1111b;易碎砖块的颜色—高亮白色brick_color2 db 1010b;普通砖块的颜色—浅绿色brick_color3 db 0101b;硬质砖块的颜色—品红色inmenu_color db 1110b; 内部菜单的颜色—黄色wave_brick_color db 1001b;飘动档板的颜色—浅蓝色 ;********************************************************* exitflag dw 1;用来记录玩家什么时候要退出游戏,当为0时退出 stopflag dw 0;用于记录什么时候暂停,如果是1则暂停 replayflag dw 0;用于记录是否重新开局,1为有效 propflag db -1;用来判断当前屏幕中是否有道具,如果没有则为-1,否则为相应的第0到n个道具 speedflag dw 0;用来判断是否要加速,如果为1则为加速 cmpgameflag db 0;用来记录游戏中的所有砖块是否打完,如果打完则为1 inmenuflag db 1;这个变量只是在最开始进入画面时用到,为了防止中断打断,因此init中不需要对它初始化,1为有效 balldeadflag db 0;判断小球的生命值是不是都打完了,如果为1,那么就意味着小球死光光了 barflag db 1;用于记录是第几关,一共有5关 bomb_flag db 0;用于显示当接到bomb后的特效,当为0时说明没有特效 ;********************************************************** ;一些要显示的字符 brick_msg db 'BRICK$' mader_msg db 'MADE BY: XJTUSE$' play_msg db 'Press space to play!$' score_msg db 'Score:$' life_msg db 'Life:$' prop_msg db 'PROP$' none_msg db 'NULL $' hint_msg1 db ' HINT$' hint_msg2 db '<Esc>:exit $' hint_msg3 db 'Space:pause$' hint_msg4 db '<R>: replay$' ;这些msg是用在道具的提示上的 addlife_msg db 'LIFE $' ;奖生命addscore_msg db 'SCORE $' ;奖分数speed_up_msg db 'SPEED UP $' ;球加速speed_down_msg db 'SPEEDDOWN$' ;球减速large_racket_msg db 'L RACKET $' ;大球拍small_racket_msg db 'S RACKET $' ;小球拍bomb_msg db 'BOMB $' ;普通炸弹bigbomb_msg db 'SUP BOMB $' ;超级炸弹stop_msg db 'Press space to continue!$'; 当暂停的时候要调用这个 con_msg db ' $';继续玩的时候,将之前的那个字体给涂成黑色 lose_msg db 'You lose! Play again?(Y/N)$';当生命值为0时要用到这个msg con1_msg db ' $';继续玩的时候,将之前的那个字体给涂成黑色 congratulation_msg db 'Congratulation!!You win!!$' youscore_msg db 'Your score is: $';分数显示 Your score is: $playagain_msg db 'Play next level?(Y/N)$' ;********************************************************* ;要记录的数值 wave_brick1 dw 15;第一个挡板的最左边的位置 wave_brick2 dw 170;第二个挡板的最右边的位置 wave_brick1_pos db 1;1为向右移动,记录第一个档板的运动方向 wave_brick2_pos db 0;0为向左移动,记录第二个档板的运动方向 count db 0;这个变量是用来记录次数的 bomb_count db 0;用于炸弹的特效 life_num db 3;记录生命值 score_num db 0;得分总和不能大于255 mouse_last dw 80;用于记录上一次的的鼠标的位置,只记录x轴 racket_width dw 30;用于记录球拍的宽度 ballx dw 90;用来记录球的左上角的x轴坐标 bally dw 183;用来记录球的左上角的y轴坐标 brick_num dw 100;用来记录砖块的数量 x dw 1;用于记录运动向量 y dw -1;用于记录运动向量 propx dw 0;这个变量是用来画道具时,储存道具的左上角的x轴信息 propy dw 0;这个变量是用来画道具时,储存道具的左上角的y轴信息 ;这个是道具的颜色,它们的顺序与下面道具的顺序一一对应 prop_color db 0001b ;增加生命的道具 db 0010b ;增加分数的道具 db 0011b ;加速的道具 db 0100b ;减速的道具 db 1000b ;大球拍的道具 db 1001b ;小球拍的道具 db 1010b ;普通炸弹的道具 db 1011b ;超级炸弹的道具 bomb_color db 1100b ;
    游戏的流程说明

    调用inmenufun函数实现进入画面利用机器画像素的延迟性,分步对屏幕中的不同的位置涂色,从而显示出动画的效果。最终将显示出游戏名称和游戏制作者等信息
    调用waitfun函数等待输入空格利用dos的int 21h中断,当无键盘(空格)输入时,一直等待键盘的中断。从而达到暂停的效果
    调用ballstep函数并对相应的flag位进行操作:先判断小球是否与其它对象是否相撞,如果相撞,那么就改变小球的运动向量,然后得到小球的下个位置。将上一帧的小球擦掉,再将刚得到的小球画出来,从而实现小球的运动。再判断小球是否是与砖块相撞,如果是与砖块相撞,那么判断那个小球的抗击力减一,如果那个小球的抗击力为0,那么将那个小球的颜色涂为背景色。再这个函数中还要对相应的flag位赋值:

    小球落地:balldeadflag置为有效
    砖块打完:cmpgameflag置为有效
    有道具产生:propflag置为有效小球落地并且小球生命为0:exitflag置为有效
    调用prop_screen函数当propflag无效时,这个函数什么都不做。当propflag有效时,这个函数将之前的道具的擦掉,然后在将道具的位置下移1,再在新的位置画出道具,从而实现道具的下落过程

    2.4 程序运行测试报告游戏的进入画面

    游戏画面



    一些关键的问题及其解决方法
    如何判断小球的撞击。因为这里涉及到小球与墙壁、小球与砖块、小球与道具、小球与球拍、小球与飘动档板等多中可能撞击,而道具的位置和飘动砖块的位置都是不可预料的,那么如果判断小球与这么多的对象是否相撞呢?刚开始准备用坐标的方式进行判断,但当小球与飘动档板和道具相撞时,老是无法识别。后来我采用了对小球的下个位置的颜色值进行读取,如果是背景颜色,那么说明那个位置是没有其它对象的,那么小球就可以移动到那个位置。如果下个位置的颜色值不是背景颜色,那么说明小球将要与其它的对象进行碰撞,那么就需要对小球的方向向量进行改变。
    另一个问题是如何通过小球与球拍的碰撞,而试小球产生出不同的方向向量呢?为了使得游戏更具有娱乐性,必须使得小球可以拥有不同的方向向量。但到底如何产生不同呢,我采用了球拍三分法,将球拍分为左、中、右三个部分,如果是小球与球拍在中间区域发生碰撞,那么小球将会发生的是正碰;如果小球与球拍在左区域发生碰撞,那么产生的方向向量将会偏左(与正碰比较);如果小球与球拍在右区域发生碰撞,那么产生的方向向量将会偏右(与正碰比较)。
    程序存在的一些问题
    汇编语言的焦点问题。由于汇编语言对多线程处理采用的是中断处理,在编程过程中也注意到了这一点,但是在后期测试的时候,多多少少还是会存在这类问题,比如提示字符串“Press space to play!”出现的位置会有变化。
    中断次数问题。由于机器和模式的原因,本程序采用的是每秒中断18.2次,应该来说正常情况下视觉上是没有问题的,但是程序采用的是鼠标控制,所以时常会出现鼠标操作速度超过了中断次数导致视觉界面出现停留。
    小球的方向变化问题。首先小球是正方形的,只不过让其显示出一个近似圆形的形状,所以在小球碰撞改变方向的时候,视觉上会略有偏差;其次小球在和下方球拍碰撞的时候,由于是不同位置应该会反射不同的角度,但是实际操作体验貌似感觉不是很明显;最后,小球在与砖块碰撞时,有时会出现貌似碰上了而且改变方向了,但易碎砖块没有任何变化。
    道具出现时机。计划中应该是在打碎某个砖块时出现道具,结果在某些情况下会无缘的从屏幕某个地方出现道具。
    3 结论3.1 总结经过这次的汇编专题实验之后,我感觉自己对汇编语言的理解更加深刻了,上学期的课内实验虽然在一定程度上促进了理论与实践的结合,但是却很有限,而这次的专题实验无论是规模上、难度上,还是老师和我的重视程度上,都是课内实验所不能比拟的。
    实验开始时的选题报告,我经过对多个实验项目进行综合比较,结合自己的实际情况和兴趣爱好,最终选择了经典游戏打砖块。然而在对实验的具体方向和目标特色方面不是很清楚,经过马老师认真细致的指导,帮助我深入认识了自己的主题,如何能够展现出自己的特色,突出自己与别人不一样的地方,而且就实验中的一些细节与我展开了深入的对话。这个交流从根本上改变了我对自己项目的认识,也明确了从何处入手,把何处作为重点,如何促进实验的成功等很多具体详实的细节。实验过程中,应该说困难相当多。最大的困难不是技术不熟悉,不是知识点没掌握,而是战线拉的太长导致的遗忘。由于汇编语言的特点,jmp的不断频繁出现,所以在一定时间之后,很容易模糊自己上次的努力方向和方法,然后就会花费大量时间来回顾和总结,结果在进度上有所延后。在中后期,我注意到了这个问题,所以几乎将程序的每一行都加了注释,每一小部分都描述了功能而且彼此隔开,每一大部分都独立成一体,除此之外,我还用文档的形式记录项目的进展、项目主要函数的功能,以方便查阅。
    在后期的汇总过程中,突出的问题是发现了问题却无能为力。因为汇编语言特有的特点,项目完成后修改错误变的极为困难,有时即使可以修改也不敢去动,而只是在其他方面做些相对必要的修缮,这是因为汇编程序牵一发而动全身,一旦出错,只能回滚重来,高级语言程序的测试改错策略对汇编语言基本没用,汇编语言程序要想做的好,必须在构思、设计阶段做好充分的工作,而不能指望后期的测试。
    3.2 展望这次实验总体上是成功的,我从中也学到了不少东西,但是发现的问题仍然很多,在此次专题实验结束之后,有些问题或许需要更长的时间来品味和思索,留给我去探索的路还很漫长。一次实验是有结束期的,而我对未来对前景的追求是没有结束的,如何更好的运用此次实验中获得的经验,如何在将来的生涯中避免出现此次实验中的问题,仍然有很长的路要走。
    这次实验带给我观念上的转变是巨大的。汇编语言的特点给我在思想上做了一个较大的修正,改变了以往高级语言的思维,使我对计算机底层的认识更加深入,也是我懂得了高级语言背后的本质。汇编语言的核心我似有涉及,但是完全不深入,对汇编的认识也停留在高级语言的替代方面,因此在以后的学习生活中,如何把握汇编的核心也需要慢慢去体会。
    4  留言 2019-05-31 12:02:09
  • 基于HTML实现的游戏专题网站

    摘 要大观园系列是游民星空出品的向广大用户提供了解新上市游戏的方便途径,上玩家直观的看到游戏界面,内容,人物设定,剧情等重要信息,促使玩家购买。提供方便的同时,也增加了网站浏览量。大观园:尼尔机械纪元篇是为了2017-03-17上市的游戏《尼尔机械纪元》制作的网页,以文字及视频的方式介绍了游戏的背景故事,主角资料。同时提供了正版游戏购买链接。美观的界面设计是本次设计的重点,为了让玩家有良好的用户体验,对网页排版,UI交互,做了精心的设计。尽量达到模仿游戏内交互界面的样式。
    关键词:尼尔:机械纪元、游戏介绍类网页、UI设计、视觉效果
    第一章 网站开发的背景知识与相关技术1.1 相关产业背景知识游戏是时代的产物,是随着游戏业的蓬勃发展而产生的。随着互联网技术的不断发展,人们对于游戏类网页设计的要求越来越高,除了要求能满足实用性的目的以外,还开始追求富有艺术特征的视觉表现效果。由于游戏类网页设计涉及多门学科,人们大多会从技术方面来探讨。认为好的网页设计所依赖和展示的是一种新的技术形式,往往忽视了艺术方面的表现。其实,游戏网页的艺术表现形式也必须得到重视。与传统平面设计相比,游戏类网页设计具有一种新的视觉表现形式,值得我们进行深入研究,提出比较系统的设计理论。随着信息技术的不断发展,游戏类网页作为游戏的宣传展示与交流平台,必然会随之不断发展与更新。如何紧跟时代发展的潮流,使游戏网页的设计水平不断提高,以更好的视觉表现形式呈现给人们,是我们必须要关注与探讨的话题。
    游戏作为一门新生的艺术,具有独立的美学范式和艺术结构。游戏交互设计的优劣,直接影响着玩家的游戏体验和感性判断。游戏界面作为人机交互的桥梁,其作用无可取代。游戏玩家对游戏的直观印象,一个来自操作,另一个就是画面。游戏界面本身就是画面的一部分,其地位举足轻重。
    界面设计应该是游戏设计中非常重要的一个环节,玩家与游戏系统的直接交互就是通过界面系统完成的。游戏的界面跟产品的外观和功能一样,要能吸引玩家并且易用。在设计界面的过程中,要一直注重易用性设计原则,并且充分考虑用户感受,随时调整和修改界面的设计细节。
    游戏界面既具有界面设计的一般规律,更有游戏这一特殊领域的个性设计原则。在界面的设计制作过程中,应在掌握基本游戏框架设定能力和对用户需求分析能力的基础上,了解并掌握游戏开发机制尤其是游戏界面的实现原理以及设计中常用的技术,例如:界面风格制定、美术需求文档制作、界面原型制作、程序坐标图制作等技术。
    如今外国游戏已经在中国市场占有很重要的地位,使得中国的文化环境逐渐改变,民族文化已经不能吸引玩家,尤其近年来屡屡的事件和媒体舆论的影响,已经让网络游戏成为大众眼中毒害青少年的精神毒品。而宣传中国传统文化,引导青少年健康游戏、快乐游戏应该是每个游戏工作者的责任和义务。
    就中国的游戏现状来说,游戏是人类的天性,网络是现代信息社会的宠儿,二者有机结合而诞生的网络游戏就拥有了巨大的客户资源。目前,全球电脑游戏行业已经成为电影、电视、音乐并驾齐驱的最为重要的文化娱乐产业之一,其年销售额已经超过好莱坞的全年收入。亚洲是世界游戏市场的核心力量之一,而韩国与台湾成为全球最大的两个网络游戏市场。中国的网络游戏虽然刚刚起步,但是其以惊人的发展速度、巨大的经济利益以及对游戏用户的广泛影响吸引了政府、企业、学者等社会各界人士的目光。
    网络游戏产业本身具有相当大的商业价值,也具有广泛的价值链。对电信、IT、媒体等贡献巨大,已经展现出成为一个巨大的新兴产业的潜力、中国的网络游戏市场得到了中国电信的巨大支持,并且拥有巨大的用户资源,目前已经处于起步阶段,市场增长非常迅速。
    1.2 前端开发环境的技术介绍1.2.1 Visual Studios Code本次使用的前端开发工具为visual studios code。
    Visual studios code 是一款微软刚发布的轻量级文本编辑器,是一个我喜爱的 Visual Studio 的免费,轻量,跨平台版本。简单的安装之后,就可以在 Windows、Mac 或 Linux 机器上享受 Visual Studio 的绝大多数功能。这里突出展示了十个 VS Code 引人注目的特性,VS Code 的目标是成为在任何开发平台上的一站式代码编辑器。
    海量的语言支持 VS Code不只是跨平台, 它想成为支持30多种语言的开箱代码编辑器。可以编辑C#, VB, JavaScript, HTML, CSS, Typescript, Ruby, Objective-C, PHP, JSON, Less, Sass 还有 Markdown, 这只是列出来一点点而已。你可以得到内嵌语法高亮和分支匹配, 当然也少不了代码导航。 VS Code旨在成为Node.js, ASP.NET 和 Typescript 开发的首选IDE, 剑指先进web/cloud 应用。作为 ASP.NET 5 的开发工具,VS Code 已经是一个富编辑器,它内置具备很多日常功能。简单使用有效的 Yeoman 工具产生你的 ASP.NET 5 web 应用框架,并指向其根目录。你找到了一个功能丰富的 IDE(示例项目截图),它的 Omnisharp-powered 为代码提供了智能感知,错误,命令,部署和集成版本控制功能。所有的这些设计可以保持现代,精益,跨平台的 ASP.NET 5 web 开发在 VS Code 上的所需。
    并排编辑 vs code 支持的其最受欢迎的开发人员的要求之一—并排编辑代码。简单的命令,在你的项目浏览器的文件上控制点击,多个文件可以并排打开文件。pre-docked 并且准备编辑。VS Code 可以支持三个同步的文件编辑,每个人都可以发射命令提示符。下面的屏幕快照展示了来源于一个被开放地并排编辑的 asp.net 项目的两个文件。
    自动补全代码 如果没有了 Visual Studio 的智能感应,你不会想写 .NET 代码,对吧?VS Code 知道这些并且尝试着令人满意的创造性的智能感应。确保基于语言特性你能获得友好的提示,同时在你自己写的代码里结合上下文智能感应。
    控制面板 VS 代码中有一个强大、方便的功能就是控制面板—通过简单的单击键盘Command或者Control + Shift + P来使用。考虑到它是你IDE中的PowerShell,为常用任务准备一个快捷方式。而且,如果你部署的相聚支持特定的命令行工具,VS代码控制面板是很聪明的,足以理解并提供帮助。举个例子,在我的ASP.NET 5 web应用中,Project.JSon列出了一些特定的DNX(可执行的.NET)命令,后面会给出。在你开始键入这些可是别的命令时,控制面板提供IntelliSense帮助,甚至出现为可执行的任务提供命令提示。
    函数参数 VS Code 有很优美的智能感知功能,帮助我们在相应的调用中输入函数参数,因此能很轻松地完成代码。这是与编程语言/系统函数相关的功能,除此之外,它智能地对你的代码中的自定义函数提供了帮助。下面的截图显示,为函数调用提供了输入参数,在这个工程里的任何地方 VS Code 都能看到被定义了的函数。并且很流畅。
    信息预览作为开发者,你可能常常想要预览一个文件,或检查一个函数的定义。 但是,一个完整的上下文切换的消耗很大,因为它让你无法继续输入。在 VS Code 中输入预览帮助,只需单击右键,或者F12。— 这样预览定义(Peek Definition)就会出现,预览的结果内嵌在编辑器中,敲击 Escape 键后退出,这样节省了大量的上下文切换的时间。
    Markdown调试大多数开发者都拥有他们最喜欢的 Markdown 编辑器—快速输入 Markdown,然后预览 HTML。VS Code 有意接管 Markdown 编辑,同时 VS Code 也具备这样的实力。你可以得到一致的Markdown 编辑支持,准备好以后,简单的触发 ⇧⌘V 来查看预览,如下所示。这里也有按钮,用来在编辑/预览之间切换,同样,它也会将预览窗口并排放置,以便查看变动。
    调试开发者整天写代码时处在一种编辑/编译/调试的循环中,对于现代的任何 IDE 如果没有可靠的调试支持都是一种残缺。VS Code 已经对Node.js 开发提供可靠的支持并且接下来的计划对 ASP.NET 5 开发提供最好的调试体验,在不久的将来。
    1.2.2 PhotoshopPhotoshop是一款图像处理软件,由Adobe公司于上世纪80年代末期推出是专门用于图形图像处理的软件。他功能强大、集成度高、并且适用面广、操作简便。它不仅提供了强大的绘图工具,可以绘制艺术图形,还能从扫描仪、数码相机等设备采集图像,对它们进行修改、修复,调整图像的色彩、亮度,改变图像的大小,还可以对多幅图像进行合并增加特殊效果。
    Photoshop中文意思是“照片商店”也可被称为“思想的相机”是目前最流行的图像设计与制作工具。它不仅能够真实地反映现实世界,而且能够创造出虚幻的景物,还可以创建成百上千种特效文字,根据自己的思想制作几十种纹理效果。学会并灵活运用Photoshop,每个人都可能成为图形图像方面的专家,使你创作的作品达到专业水平。处理图像尺寸和分辨率:

    可以按要求任意调整图像的尺寸,分辨率就是指图像显示的精密度
    在ps中还可以在不影响尺寸的同时增减分辨率,以适应图像的要求

    这样可以方便我们裁剪图像某部分的内容。
    图层功能:PS支持多图层工作方式,可以对图层进行合并、合成、翻转复制和移动等操作,PS的特效也都可以用在图层的上面。此外图层还可以进行像素的色相、渐变和透明度等属性的调整。我们还可以将图像从一个图层复制到另一个图层之中。
    绘画功能:我们可以使用喷枪工具、画笔工具、铅笔工具、直线工具来绘制图形,此外还使用文字工具来在图像之中添加文本,
    选取功能:矩形选区工具和椭圆选区工具可以选择一个或多个不同大小或不同形状的范围。套索工具可以选取不规则形状的图形。魔术棒工具可以根据颜色范围自动选取所需部分。色调和色彩功能:对图像进行色彩色调的调整
    图像的旋转和变形:可以将图像进行翻转和旋转,还可以将图像进行拉伸、倾斜和自由变形等处理。
    颜色模式:PS具有多种的颜色模式,包括黑白、灰度、双色调、索引色、HSB、Lab、RGB和CMYK等模式。其中最主要的是CMYK和RGB模式。
    1.3 前端开发的技术介绍1.3.1 HTML5HTML5是HTML最新的修订版本,2014年10月由万维网联盟(W3C)完成标准制定。HTML5的设计目的是为了在移动设备上支持多媒体。
    语义特性(Class:Semantic)
    HTML5赋予网页更好的意义和结构。更加丰富的标签将随着对RDFa的,微数据与微格式等方面的支持,构建对程序、对用户都更有价值的数据驱动的Web。
    本地存储特性(Class: OFFLINE & STORAGE)
    基于HTML5开发的网页APP拥有更短的启动时间,更快的联网速度,这些全得益于HTML5 APP Cache,以及本地存储功能。Indexed DB(html5本地存储最重要的技术之一)和API说明文档。
    设备兼容特性 (Class: DEVICE ACCESS)
    从Geolocation功能的API文档公开以来,HTML5为网页应用开发者们提供了更多功能上的优化选择,带来了更多体验功能的优势。HTML5提供了前所未有的数据与应用接入开放接口。使外部应用可以直接与浏览器内部的数据直接相连,例如视频影音可直接与microphones及摄像头相联。
    连接特性(Class: CONNECTIVITY)
    更有效的连接工作效率,使得基于页面的实时聊天,更快速的网页游戏体验,更优化的在线交流得到了实现。HTML5拥有更有效的服务器推送技术,Server-Sent Event和WebSockets就是其中的两个特性,这两个特性能够帮助我们实现服务器将数据“推送”到客户端的功能。
    网页多媒体特性(Class: MULTIMEDIA)
    支持网页端的Audio、Video等多媒体功能, 与网站自带的APPS,摄像头,影音功能相得益彰。
    三维、图形及特效特性(Class: 3D, Graphics & Effects)
    基于SVG、Canvas、WebGL及CSS3的3D功能,用户会惊叹于在浏览器中,所呈现的惊人视觉效果。
    性能与集成特性(Class: Performance & Integration)
    没有用户会永远等待你的Loading——HTML5会通过XMLHttpRequest2等技术,解决以前的跨域等问题,帮助您的Web应用和网站在多样化的环境中更快速的工作。
    CSS3特性(Class: CSS3)
    在不牺牲性能和语义结构的前提下,CSS3中提供了更多的风格和更强的效果。此外,较之以前的Web排版,Web的开放字体格式(WOFF)也提供了更高的灵活性和控制性。
    DIV+CSS
    CSS语言是一种标记语言,它不需要编译,可以直接由浏览器解释执行(属于浏览器解释型语言). 在标准网页设计中CSS负责网页内容(XHTML)的表现. CSS文件也可以说是一个文本文件,它包含了一些CSS标记,CSS文件必须使用css为文件名后缀。
    刚学习网页制作时,总是先考虑怎么设计,考虑那些图片、字体、颜色、以及布局方案。然后我们用Photoshop或者Fireworks画出来、切割成小图。最后再通过编辑HTML将所有设计还原表现在页面上。如果你希望你的HTML页面用CSS布局(是CSS-friendly的),你需要回头重来,先不考虑“外观”,要先思考你的页面内容的语义和结构。 外观并不是最重要的。一个结构良好的HTML页面可以以任何外观表现出来,CSS Zen Garden是一个典型的例子。CSS Zen Garden帮助我们最终认识到CSS的强大力量。HTML不仅仅只在电脑屏幕上阅读。你用photoshop精心设计的画面可能不能显示在PDA、移动电话和屏幕阅读机上。但是一个结构良好的HTML页面可以通过CSS的不同定义,显示在任何地方,任何网络设备上。 开始思考 首先要学习什么是”结构”,一些作家也称之为”语义”。这个术语的意思是你需要分析你的内容块,以及每块内容服务的目的,然后再根据这些内容目的建立起相应的HTML结构。
    JavaScript
    JavaScript脚本语言具有以下特点:

    脚本语言。JavaScript是一种解释型的脚本语言,C、C++等语言先编译后执行,而JavaScript是在程序的运行过程中逐行进行解释。
    基于对象。JavaScript是一种基于对象的脚本语言,它不仅可以创建对象,也能使用现有的对象。
    简单。JavaScript语言中采用的是弱类型的变量类型,对使用的数据类型未做出严格的要求,是基于Java基本语句和控制的脚本语言,其设计简单紧凑。
    动态性。JavaScript是一种采用事件驱动的脚本语言,它不需要经过Web服务器就可以对用户的输入做出响应。在访问一个网页时,鼠标在网页中进行鼠标点击或上下移、窗口移动等操作JavaScript都可直接对这些事件给出相应的响应。
    跨平台性。JavaScript脚本语言不依赖于操作系统,仅需要浏览器的支持。因此一个JavaScript脚本在编写后可以带到任意机器上使用,前提上机器上的浏览器支 持JavaScript脚本语言,目前JavaScript已被大多数的浏览器所支持。[3]

    不同于服务器端脚本语言,例如PHP与ASP,JavaScript主要被作为客户端脚本语言在用户的浏览器上运行,不需要服务器的支持。所以在早期程序员比较青睐于JavaScript以减少对服务器的负担,而与此同时也带来另一个问题:安全性。而随着服务器的强壮,虽然程序员更喜欢运行于服务端的脚本以保证安全,但JavaScript仍然以其跨平台、容易上手等优势大行其道。同时,有些特殊功能(如AJAX)必须依赖Javascript在客户端进行支持。随着引擎如V8和框架如Node.js的发展,及其事件驱动及异步IO等特性,JavaScript逐渐被用来编写服务器端程序。
    第二章 总体设计2.1 模块化设计总方案为了实现网站功能,本网站主要分为两个网页,进入网站的主题网页index.html。之后的导航网页demo.html。主页包括着游戏简介,游戏CG预告视频。导航网页包括着转场动画,标题Logo,导航菜单,导航菜单子菜单中的具体界面。具体设计如下。
    2.2 网站功能结构2.2.1主页面结构主页拥有一个动态背景,使用游戏的宣传CG,再有一个简介框在右边,显示游戏简介,和一个链接按钮。

    2.2.2主页面结构导航页面有一个动态logo作为背景,3个菜单选项,点击进入不同的界面。

    2.3 模块功能设计2.3.1 主页模块化设计
    背景用<video>标签,内置游戏CG视频,简介框用<div>标签嵌套<p>标签,写入文字,按钮用<button>标签,链接到下个界面。布局如下所示:

    2.3.2 导航菜单模块化设计
    打开后首先是loading动画,显示加载动画,效果结束后显示导航菜单,分为几大<div>结构,<bground>里是主菜单界面,<bgnier>里是主角资料,从主菜单点击相应按钮之后显示该div隐藏主菜单div。<bginfo>里是游戏背景故事,从主菜单点击相应按钮之后显示该div隐藏主菜单div。<bgfirst>是子菜单返回主菜单按钮。
    主菜单布局如下:

    游戏背景及主角资料布局如下:

    第三章 详细设计3.1 主页面详细设计3.1.1 HTML设计主页面的html结构:<body>包括着<video>的视频背景和<div><p><button>等标签组成的简介信息。代码如下
    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <link href="css/index.css" rel="stylesheet" type="text/css" /></head><body> <video id="bgvid" playsinline autoplay loop> <!-- WCAG general accessibility recommendation is that media such as background video play through only once. Loop turned on for the purposes of illustration; if removed, the end of the video will fade in the same way created by pressing the "Pause" button --> <source src="./video/NieR_1.mp4" type="video/webm"> <img src="./image/NieR_2.jpg"> </video> <div id="NieR"> <h1>NieR</h1> <p>《尼尔:机械纪元(NieR:Automata)》</p> <p>Square Enix发行的一款动作RPG游戏, 讲述了在被摧毁的地球上由人类的敌人外星人派来的机械生命体与人类方派出的人造人“尤尔哈(YoRHa)”部队进行战斗的故事。 游戏背景设定在和《尼尔》相同的世界,并将有一个全新的故事剧情,但和前作几乎没有关联。</p> <p> 游戏讲述在被摧毁的地球上由人类的敌人外星人派来的机械生命体与人类方派出的人造人“尤尔哈(YoRHa)”部队进行战斗的故事。 主角叫做“尤尔哈2号B型”人造人,擅长使用刀和长剑,在战斗过程中可以随时切换。而游戏中还有被称为“POD”的机器人进行远距离支援攻击。 游戏里面充斥着各种暴力元素,这非常符合日系游戏的特点。 女主角孤身一人,蒙着眼睛,与各种各样的机器人搏斗。 </p> <button id="btn">Link</button> </div></body></html>
    3.1.2 JS设计该页面的js设计,实现跳转到下一个导航界面,代码如下:
    <script> var btn = document.getElementById('btn'); btn.onclick = function(){window.location.href = './demo.html';}</script>
    3.1.3 CSS设计以下是该页面的css设计,实现布局美化及UI美化,优化用户体验实现半透明的信息框,让用户看的到简介文字的同时又不会挡住视频,代码如下:
    * { margin: 0px; padding: 0px;}video { position: fixed; top: 50%; left: 50%; min-width: 100%; min-height: 100%; width: 100%; height: auto; z-index: -100; transform: translateX(-50%) translateY(-50%); background-size: cover; transition: 1s opacity;}.stopfade { opacity: .5;}#NieR { font-family: Agenda-Light, Agenda Light, Agenda, Arial Narrow, sans-serif; font-weight: 100; background: rgba(192, 192, 192, 0.3); color: white; width: 33%; padding: 1rem; margin: 2.6rem; float: right; font-size: 1.2rem;}p{ padding: 1.3rem;}h1 { font-size: 4rem; text-transform: uppercase; margin-top: 0; letter-spacing: .3rem;}#NieR button { display: block; width: 80%; padding: .4rem; border: none; margin: 1rem auto; font-size: 1.3rem; background: rgba(255, 255, 255, 0.23); color: #fff; border-radius: 3px; cursor: pointer; transition: .3s background; }#NieR button:hover { background: rgba(0, 0, 0, 0.5);}
    3.2 导航界面详细设计3.2.1 HTML设计导航页面的html结构:<bgfirst>是开始时加载动画,< bground>是主页面导航主菜单还有动态logo,< bgnier>是主角资料加上主角图片,< bginfo>是游戏背景故事。代码如下:
    <!DOCTYPE html><html><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <link rel="stylesheet" type="text/css" href="dist/typeit.min.css"> <link rel="stylesheet" href="css/demo.css"> <script src="js/jquery-2.1.4.min.js"></script> <script src="dist/typeit.min.js"></script></head><body> <div id="bground"> <audio autoplay="autoplay" loop="loop"> <source src="./video/NieR.mp3" type="audio/mp3"/> </audio> <video class="page_bg" autoplay="true" loop> <source src="./video/startloopvd.mp4" type="video/mp4"> <img class="page_bg" src="http://image.gamersky.com/zqimg/nierautomata2/preview/ztimages/bg_begin.jpg" alt="replace"> </video> <div class="startTit" data-txt="尼尔:机械纪元">尼尔:机械纪元</div> <div class="startMenu"> <a class="startgame animFlr anim5" id="nier"> <span>主角资料</span> <i></i> </a> <a class="gameinfo animFlr anim6" id="info"> <span>游戏资料</span> <i></i> </a> <a class="buygame animFlr anim7"> <span>购买游戏</span> <i></i> </a> </div> </div> <div id="bgnier"> <div class="animateBg"> <img src="./image/bg_infos.jpg" alt="bg" class="ab_bg"> </div> <div class="infos_hw infos_hw1"><i></i></div> <div class="infos_hw infos_hw2"><i></i></div> <div id="infosCon" class="infos_con"> <div class="infos_tit_wrap"> <div class="infos_tit"> <span>主角资料</span><i>INFO</i> </div> </div> <div class="infos_main"> <div class="infos_story"> <div class="txtwrap"> <p><span>尤尔哈二号B型 冷静的意志之刃</span></p> <p>作为人型机械兵部队尤哈尔的一员被派遣</p> <p>战斗通用型的人工智能</p> <p>可以使用双长剑近距离攻击</p> <p>也能使用支援系统“POD”机器人远程攻击</p> <p>因为装备作战眼罩,平时基本看不到她的神情</p> <p>尤尔哈部队成员都没有名字,全部用代号称呼</p> <p>虽然原则上禁止拥有感情</p> <p>但是因为个体差异,2B的性格较为冷静。</p> <p><span>CV:石川由依</span></p> </div> </div> <div class="image"> <img src="./image/NieR_3.png"/> </div> </div> <div id="fixNav"> <a class="fx_home" id="fx_home2"><span>返回首页</span></a> </div> </div> </div> <div id="bginfo"> <div class="animateBg"> <img src="./image/bg_infos.jpg" alt="bg" class="ab_bg"> </div> <div class="infos_hw infos_hw1"><i></i></div> <div class="infos_hw infos_hw2"><i></i></div> <div id="infosCon" class="infos_con"> <div class="infos_tit_wrap"> <div class="infos_tit"> <span>故事背景</span><i>STORY</i> </div> </div> <div class="infos_main"> <div class="infos_story"> <div class="txtwrap"> <p>《尼尔:机械纪元》游戏故事发生在遥远的未来。</p> <p>来自外星的入侵者毫无征兆地攻击了地球,并释放出新的威胁:一种名为机械生命体的武器。</p> <p>人类在无力抵抗这种威胁的情况下逃往月球。</p> <p>人类委员会组织了一支由人形机器人组成的抵抗军队,来夺回地球。</p> <p>为了打破僵局,抵抗军部署了一个新的机器人部队:尤尔哈。</p> <p>机械生命体和人形机器人之间的一场大战一触即发。</p> <p>随着战争的进行,被遗忘已久的世界的真相也将浮出水面……</p> </div> </div> </div> <div id="fixNav"> <a class="fx_home" id="fx_home"><span>返回首页</span></a> </div> </div> </div> <div id="bgfirst"> <div id="input"> <p class="example1"></p> </div> <input type="button" class="btn" id="btn" value="overclocking" /> </div></body></html>
    3.2.2 JS设计使用打字机实现加载画面的文字打字效果,插件点击主菜单的不同选项,使主菜单隐藏,相应的div的display属性设为block。,使之显示出来使用户感觉像是跳转页面。代码如下:
    <script> $('.example1').typeIt({ whatToType: ["正在加载,正在启动系统", "正在开始系统检查", "记忆单元检测:正常","正在初始化战术记录","正在加载地形数据", "体征检测:正常","剩余MP检测","黑匣子温度:正常","黑匣子内部压力:正常", "正在启动IFF","正在启动FCS","装备认证:完成","系统:完全检测","战斗准备完成"], typeSpeed: 50 }); </script> <script> var oNier = document.getElementById('nier'); var oBtn = document.getElementById('btn'); var oInfo = document.getElementById('info'); var oHome = document.getElementById('fx_home'); var oHome2 = document.getElementById('fx_home2'); var oDiv1 = document.getElementById('bgfirst'); var oDiv2 = document.getElementById('bground'); var oDiv3 = document.getElementById('bginfo'); var oDiv4 = document.getElementById('bgnier'); oBtn.onclick = function () { if (oDiv1.style.display == 'block') { oDiv1.style.display = 'none'; oDiv2.style.display = 'block'; } else { oDiv2.style.display = 'none'; oDiv1.style.display = 'block'; } }; oInfo.onclick = function(){ if (oDiv2.style.display == 'block') { oDiv2.style.display = 'none'; oDiv3.style.display = 'block'; } else { oDiv3.style.display = 'none'; oDiv2.style.display = 'block'; } }; oHome.onclick = function(){ if (oDiv3.style.display == 'block') { oDiv3.style.display = 'none'; oDiv2.style.display = 'block'; } else { oDiv2.style.display = 'none'; oDiv3.style.display = 'block'; } }; oHome2.onclick = function(){ if (oDiv4.style.display == 'block') { oDiv4.style.display = 'none'; oDiv2.style.display = 'block'; } else { oDiv2.style.display = 'none'; oDiv4.style.display = 'block'; } }; oNier.onclick = function(){ if (oDiv2.style.display == 'block') { oDiv2.style.display = 'none'; oDiv4.style.display = 'block'; } else { oDiv4.style.display = 'none'; oDiv2.style.display = 'block'; } } </script>
    3.2.3 CSS设计以下是该页面的css设计,实现布局美化及UI美化,优化用户体验实现,当光标移动到菜单时有即时反馈,看的到菜单选项下多了反馈效果。各个DIV里定位不同Div的位置,背景。代码如下:
    *{ margin: 0px; padding: 0px;}#bgfirst{ font-family: Agenda-Light, Agenda Light, Agenda, Arial Narrow, sans-serif; width: 100%; height: 870px; background: black; color: white; display: block; font-size: 1.2rem; padding: 50px;}#bgfirst #input{ height: 700px;}#bgfirst .btn{ display: block; width: 30%; padding: .4rem; border: none; margin: 1rem auto; font-size: 1.3rem; background: rgba(255, 255, 255, 0.23); color: #fff; border-radius: 3px; cursor: pointer; transition: .3s background; }#bgfirst .btn:hover { background: rgba(0, 0, 0, 0.5);}#bground{ width: 100%; height: 100%; display: none;}#bground img{ width: 100%; height: 100%;}#bground .page_bg{ width: 100%; height: 100%;}#bgrond .vdLoop{ width: 100%; height: 100%;}.startMenu{ position: absolute; left: 38.5%; top: 65%; width: 330px;}.startTit{ position: absolute; left: 40%; top: 55%; overflow: hidden; width: 280px; font-size: 25px; color: #fff; text-align: center;}.startMenu a { display: block; position: relative; margin-bottom: 8px; font-size: 15px; color: #fff; text-align: center; -moz-user-select:none;}.startMenu a i { display: block; position: absolute; bottom: -2px; left: 20%; width: 200px; height: 2px; background-color: #fff; -webkit-box-shadow: 2px 2px 0 rgba(35,26,36,.8); box-shadow: 2px 2px 0 rgba(35,26,36,.8); -webkit-transition-duration: .15s; transition-duration: .15s; opacity: 0; visibility: hidden; -webkit-transform: scale(.8,1); -ms-transform: scale(.8,1); transform: scale(.8,1);}.startMenu a:hover i { opacity:1; visibility:visible; -webkit-transform:scale(1); -ms-transform:scale(1); transform:scale(1)}#bgnier{ display: none;}#bgnier .animateBg .ab_bg{ position: absolute; left: 0; top: 0; width: 100%; height: 100%; z-index: -10; background: repeat-y;}#bgnier .infos_hw { position: absolute; left: 0; width: 100%; height: 31px; border-top: 3px solid #434231; top: 100px;}#bgnier .infos_hw1 { top: 100px;}#bgnier .infos_hw2 { top: 680px;}#bgnier .infos_hw i { display: block; margin: 0 67px; height: 31px; background: url(http://image.gamersky.com/zqimg/nierautomata2/preview/ztimages/bg_hw.png) repeat-x;}#bgnier .infos_con { position: absolute; left: 0; top: 150px; width: 100%; height: 400px;}#bgnier .infos_con .infos_tit_wrap { margin-bottom: 20px; padding-left: 50px; height: 64px;}#bgnier .infos_con .infos_tit_wrap .infos_tit { color: #434231; text-shadow: 7px 7px 0 rgba(128,120,96,.42); letter-spacing: 15px;}#bgnier .infos_con .infos_tit_wrap .infos_tit span { font-size: 30px;}#bgnier .infos_con .infos_tit_wrap .infos_tit i { margin-left: 27px; font-style: normal; font-size: 25px; letter-spacing: 10px;}#bgnier .infos_con .infos_main { position: relative; margin-left: 50px; height: 400px;}#bgnier .infos_con .infos_main .infos_story { position: absolute; left: 57px; top: 50%; padding: 14px 0; width: 700px; height: auto; background-color: #dcd6b8; -webkit-transform: translate(0,-50%); -ms-transform: translate(0,-50%); transform: translate(0,-50%); -webkit-box-shadow: 2px 2px 0 rgba(95,85,55,.42); box-shadow: 2px 2px 0 rgba(95,85,55,.42);}#bgnier .infos_con .infos_main .image { position: absolute; left: 600px; top: 10%; padding: 14px 0; width: 200px; height: auto; background-color: #dcd6b8; box-shadow: 2px 2px 0 rgba(95,85,55,.42);}#bgnier .infos_con .infos_main .infos_story::before { position: absolute; left: -57px; top: 0; height: 100%; display: block; content: ''; width: 4px; border-left: 16px solid rgba(67,66,49,.3); border-right: 5px solid rgba(67,66,49,.3);}#bgnier .infos_con .infos_main .infos_story .txtwrap { margin: 0 auto; padding: 10px 0; width: 650px; border: 2px solid #928b70; border-left: none; border-right: none;}#bgnier .infos_con .infos_main .infos_story .txtwrap p { padding: 0 6px; height: 42px; line-height: 42px; font-size: 15px; color: #434231; margin: 0; padding: 0; list-style: none;}#bgnier .infos_con .infos_main .infos_story .txtwrap p span{ font-size: 20px;}#bginfo{ display: none;}#bginfo .animateBg .ab_bg{ position: absolute; left: 0; top: 0; width: 100%; height: 100%; z-index: -10; background: repeat-y;}#bginfo .infos_hw { position: absolute; left: 0; width: 100%; height: 31px; border-top: 3px solid #434231; top: 100px;}#bginfo .infos_hw1 { top: 100px;}#bginfo .infos_hw2 { top: 680px;}#bginfo .infos_hw i { display: block; margin: 0 67px; height: 31px; background: url(http://image.gamersky.com/zqimg/nierautomata2/preview/ztimages/bg_hw.png) repeat-x;}#bginfo .infos_con { position: absolute; left: 0; top: 150px; width: 100%; height: 400px;}#bginfo .infos_con .infos_tit_wrap { margin-bottom: 20px; padding-left: 50px; height: 64px;}#bginfo .infos_con .infos_tit_wrap .infos_tit { color: #434231; text-shadow: 7px 7px 0 rgba(128,120,96,.42); letter-spacing: 15px;}#bginfo .infos_con .infos_tit_wrap .infos_tit span { font-size: 30px;}#bginfo .infos_con .infos_tit_wrap .infos_tit i { margin-left: 27px; font-style: normal; font-size: 25px; letter-spacing: 10px;}#bginfo .infos_con .infos_main { position: relative; margin-left: 50px; height: 400px;}#bginfo .infos_con .infos_main .infos_story { position: absolute; left: 57px; top: 50%; padding: 14px 0; width: 1083px; height: auto; background-color: #dcd6b8; -webkit-transform: translate(0,-50%); -ms-transform: translate(0,-50%); transform: translate(0,-50%); -webkit-box-shadow: 2px 2px 0 rgba(95,85,55,.42); box-shadow: 2px 2px 0 rgba(95,85,55,.42);}#bginfo .infos_con .infos_main .infos_story::before { position: absolute; left: -57px; top: 0; height: 100%; display: block; content: ''; width: 4px; border-left: 16px solid rgba(67,66,49,.3); border-right: 5px solid rgba(67,66,49,.3);}#bginfo .infos_con .infos_main .infos_story .txtwrap { margin: 0 auto; padding: 10px 0; width: 1050px; border: 2px solid #928b70; border-left: none; border-right: none;}#bginfo .infos_con .infos_main .infos_story .txtwrap p { padding: 0 6px; height: 42px; line-height: 42px; font-size: 22px; color: #434231; margin: 0; padding: 0; list-style: none;}#fixNav{ position: absolute; right: 70px; top: 50%; z-index: 10; width: 50px;}#fixNav .fx_home{ -moz-user-select:none; position: relative; display: block; margin-bottom: 7px; width: 50px; height: 41px; background-color: #706a58; border: 1px solid #341e09; box-sizing: border-box;}#fixNav .fx_home span{ display: block; position: absolute; right: 48px; bottom: -1px; padding-top: 5px; width: 77px; height: 41px; line-height: 32px; font-size: 16px; color: #fff6e7; text-align: right; background-color: #706a58; border: 1px solid #341e09; border-right: none; box-sizing: border-box;}
    第四章 调试与测试4.1 调试过程中的主要问题在设计过程中,总先要说的就是对于软件的使用。在课堂上并没有进行软件的代码的学习,只是在图形界面进行简单的操作,有很多简单的代码却能实现很多复杂的效果,所以只能在网络上查找很多复杂的代码进行添加,并且调试,一是费时,二是即使使用了,依旧不能掌握使用方法。所以在以后的学习中更应该对软件进行深入了解,仅仅停留在初学者的阶段是不可以的。
    对于一个专业的IT人员,对于各种软件的代码的应用是必要的,同样在真正的网页制作过程中,代码也是使用最便捷功能最强大的,所以对于学习硬件的我们也应该对代码这一方面进行了解。
    同样,在专业知识,软件使用的过程中发现的难点与不足的同时,更要说明的是一种常识问题以及一些周边学科知识的空白。
    说到常识,自然是网页的结构,在我们平时的学习生活中,也会看到很多的网站,但大多大家都会关注的是它的实用内容,即使美观也只是报着欣赏的态度去看,并没有静下心来看一看,这个网站的结构布局是什么?内容部分应该怎样分类?主页与内容页的衔接?这都是平时在制作过程中所发现的不足。
    还有一点不得不说的就是周边知识的空白,比如在制作过程中,网页的颜色就涉及到色彩学,颜色与主题紧密结合,制作什么样主题的网站,使用什么样的颜色。不仅仅是主题颜色,还有各个模块间颜色的协调,让大家看起来更像一体,且颜色不唐突。什么样的颜色让人看起来更安静什么样的颜色看起来更热烈……都是我们在平时的学习中所欠缺的,专业知识固然重要,但周边知识的学习同样不可或缺。
    4.2 测试过程与结果4.2.1 主页面

    4.2.2 加载页面

    4.2.3 主菜单页面
    4.2.3 主角资料页面
    4.2.4 故事背景页面
    第五章 总结5.1 页面的设计方面网页设计跟学习别的东西一样,也需要兴趣,所谓的兴趣也不是三分钟热度,是一种执著。
    学习网页设计需要耐心,如果没有耐心,就学不好网页设计,应为当你碰到一个问题时,如果不能立刻得到问题的答案,你可能需要很长时间去解决,我就碰到过一个问题,用了很长时间才解决。
    学习网页设计需要坚持,坚持不断的学习,因为设计网页的软件在不断的更新,因此我们要不断的学习
    并且学习网页设计不要掉入技术的陷阱,如果你的网页设计技术一流,并且对软件的掌握程度已经达到一定水平,但是你设计的网页确不堪目睹,这是因为网页设计是介于平面设计和编程技术两者之间的”边缘科学.”不仅涉及到美学,心理学,平面构成,色彩搭配等平面设计的方面的知识,还涉及到html,javascript,css,asp,php等编程语言技术方面的知识.只有综合运用多种知识,才能设计出视听特效,动感十足,富于个性的web页面,才能全面展现互联网这一新型媒体的独特魅力和多维空间的超强功能。
    并且我认为网页设计应该注重实用性,因为它是让人浏览的,是用户可以抚摸,可以评论,可以交互的。因此我提倡简单的美。
    5.2 网页视觉效果视觉形象识别即我们通常所说的VI(VisualIdentity),与BI一起用于深化表现企业理念,同时也受到BI的影响。所谓视觉形象识别,就是指能够被目标客户通过视觉来认知与企业相关的一切事物,从最基础的企业标志、吉祥物、标准色到企业日常业务中的信纸、服装、名片等等,在将其系统化以后就形成了企业的视觉形象识别系统。
    视觉形象识别系统在整套CIS中处于最表层的位置,其中所有的设计都将与目标客户发生直接的接触。
    5.3 网页的整体布局和导航网页的布局通常指的是网页的整体架构,说的通俗一点就是排版。如何突出最重要的内容,即让用户第一眼就看到这个网页所想要传达的信息。这一点至关重要。在大多数做的比较成功的网页中,一个共同的特点就是网页的整体架构十分的清晰明了,便于用户浏览
    参考文献[1] 丁士锋,网页制作与网站建设实战大全[M],清华大学出版社,2013
    [2] 景新梅,软件产业原动力[J],中国计算机报,2005,7
    [3] 软件设计模式[EB/OL],www.itisedu.com/软件设计模式.htm ,2004
    [4] 袁磊,陈伟卫.网页设计与制作实例教程,清华大学出版社,2010
    [5] 崔艳清.Web程序设计与实例教程,东软电子出版社
    [6] 刘亚滨,杨红.精通Eclipse[M].北京:电子工业出版社,2003,5
    [7] 仲伟和. 基于JSP网页自动生成工具的设计与实现[J]. 科技信息(科学教研), 2007
    [8] 王征. JavaScript网页特效实例大全,清华大学出版社,2006
    [9] 项宇峰等.HTML网络编程从入门到精通.清华大学出版社.2006
    [10] Janine Warner. Mobile Design For Dummies, Wiley 2010,9
    1  留言 2019-05-27 12:04:39
  • 基于QT实现的植物大战僵尸闯关游戏

    一、本游戏的简介1.1 游戏简单的说明本游戏满足本课程大作业的所有基本要求,并且额外编写了一些特殊的功能,包括在植物方面设计编写了双发射手,机枪射手与樱桃炸弹,在僵尸方面除了撑杆跳僵尸与铁桶僵尸还编写了报纸老人僵尸这个新的僵尸。在特殊的UI设计上,还设计了原作中的小车(除草机)。在其他新奇的设计上,本游戏在战斗开始时会播放原作的背景音乐,在樱桃炸弹爆炸后会放出爆炸的声响,在撑杆跳僵尸跳跃式会发出蹦跳的声音,在报纸僵尸咆哮时会发出特殊的声音。在从卡片中选取植物时,鼠标把植物拽出时,会有一个植物的阴影显示在植物应该放在的位置上。另外要申明一点,由于大作业汇报时间紧迫,我的冷却条是关闭的,但是本游戏是有冷却条效果的,希望助教您能够了解。
    1.2 游戏架构的说明
    注释:图中的箭头有包含之一。game_window为qt提供的主类,其中game_view的实例对象client为 game_window类的成员。而game_view类的成员对象包含除了主类与自身以外的所有类。
    gamePlant, gameWeapon, gameSlot, gameZombie, gameCar与gameSun 这些类均继承于game_player头文件的gamePlayer类。gameLawn负责记录草坪各块地方植物的放置情况。以下为各类的介绍:

    gamePlant:代表各色植物的类,用来构建植物,其中含有多个布尔型变量来控制植物gif的切换,各种植物在构造函数中发出的信号不同,在timeEvent中的坐标变换与gif切换也不同。在构造函数中相应的植物会发出不同的信号,向日葵会发出需求阳光的信号,射手会发出需求弹药的信号。
    gameZombie:代表各种僵尸类,用来构建僵尸,其中含有多个布尔型变量来控制僵尸gif的切换,各种僵尸在构造函数中发出的信号不同,在timeEvent中的坐标变换与gif切换也不同。
    gameSun:代表阳光类,用来构建阳光。设置了一个布尔变量,来判断阳光是植物生产的还是屏幕生成的。在该类中mousePressEvent函数被重载来实现点击阳光阳光消失,阳光值增加25的功能。
    gameWeapon:代表子弹类,用来构建子弹。
    gameSlot:用来构建游戏卡片与,卡槽,铲子的类,该类的成员变量中设置一int型来判断是什么类型。值大于0为植物的卡片,值为-1的为卡槽,值为-2的为铲子。该类重载了mouseReleaseEvent与mouseMoveEvent两个函数。当鼠标触碰植物卡片时,会有一个植物随着鼠标移动(但是操作要注意的是鼠标左键一定要一直按下),只有当鼠标在草坪正确位置放下时才会产生植物。而铲子则与卡牌不一样,鼠标点击它图标的中间后,不用鼠标一直按着,铲子会自动跟随,点击右键铲子回到卡槽,选择植物后点击即可铲除。
    gameButton:游戏开始界面的按钮,重载了mousePressEvent与mouseReleaseEvent和mouseMoveEvent,鼠标放在其上会变色,点击后进入战斗界面。
    gameEnd:游戏的退出按钮,重载了mousePressEvent与mouseReleaseEvent和mouseMoveEvent,鼠标放在其上会变色,点击后进入游戏结束界面。
    gameCar:负责游戏的小车构建。
    gameScreen:负责游戏的各种场景构建与开始动画的产生。
    game_view: 是整个游戏的核心类,它负责把各种植物僵尸与物品加入场景中。并且监视着整个游戏的进程。

    下面介绍game_view的主要槽函数:
    void move_to_screen():用来进入战斗场景void createBullet(int ):用来生成子弹void createBomb(int ):用来生成樱桃炸弹的伤害void createMoreBullet(int ):机枪射手生成子弹void makeCard(int ):用来生成新的植物void createSun(int, gamePlant*):用来生成太阳void damageVector(gamePlant*):用来从植物的QVector中删除已死的植物void damageVector1(gameZombie*):用来从僵尸的QVector中删除已死的僵尸void showSun(gameSun*):点击阳光使得阳光消失
    1.3 游戏逻辑设计说明为了实现程序良好的封装性,本程序在game_window只是实现了一个继承于QGraphicsView的类game_view的实例化对象client的生成,以及client相应成员之间信号的连接。本程序主要的内容都是写在game_view这个类中,它负责把各种物品音效与动画加载到场景中。下面我们来一一说明。当点击游戏的开始按钮时,gameButton类会发射信号,然后game_view类会设置一个槽函数:move_to_screen(),这个槽函数会加载新的战斗场景,而信号与槽的连接是在game_window的构造函数中实现的。
    在move_to_screen()的函数中每隔20毫秒会发送信号,在game_view类的timeEvent函数接收信号后程序会自动在场景上生成僵尸。僵尸,植物与子弹都用QVector来储存,在timeEvent中会进行一个二重for循环让僵尸判断是否与子弹和植物“相遇”,如果僵尸或者植物死亡,它们各自的QVector会把他们清理掉。当鼠标点击卡片时,卡片类gameSlot会发出信号,然后在game_view中设置一槽函数make_card(int),在这个函数中会响应gameSlot发出的鼠标移动与鼠标释放的信号生成新的植物,然后信号的连接也是在game_window的构造函数中完成的。当植物需要阳光或者子弹的时候,在make_card()函数新生成植物的同时也会在植物类中发出相应的信号,game_view类中有相应的槽函数,信号的连接是在make_card()函数中,同理铲子的功能实现也是如此。另外gameLawn这个类利用不同的数组来记录新生成植物的横纵坐标与植物在草坪的放置情况,我们把其数组相应的下标传入僵尸与植物,阳光与子弹类的相应参数中然后利用connect信号槽把相应的数据传到game_view中生成相应的东西。
    对于植物和僵尸的类,是通过它们的虚拟基类gamePlayer的枚举型参数type来决定植物与僵尸的种类,这样就实现了一个构造函数通过调整一个参数的不同值来生成不同的植物与僵尸。
    二、本游戏界面UI设计首先本游戏为无尽模式,僵尸数目是无限的,所以没有植物的胜利条件,但是当僵尸成功走到屏幕最左端时僵尸获得胜利出现胜利界面。本游戏开始时有一个开始界面,界面上又开始游戏按钮,把鼠标光标放在按钮所在区域,按钮会变色。

    点击按钮,游戏进入对战界面。然后会出现开场动画与音乐,提示玩家安放植物和僵尸的即将入侵。屏幕还有滚动条方便玩家在另一侧看僵尸的行踪。屏幕上有退出按钮。

    当点击卡片的时候会产冷却条,只有冷却条结束且有足够阳光才可再点击。当拖拽植物时植物会随鼠标移动一个植物阴影会产生在植物应该放置的正确位置上。(植物不可在同一位置重复放置,且点击卡片的时候最好点击卡片部分而不是卡片的植物形象部分)如图。

    对战界面满足作业的要求,有植物的卡片,放置卡片的卡槽,铲植物的铲子,还有阳光值得显示与放置植物和僵尸移动的草坪,草坪前端还有原作中的小车。当僵尸获得胜利时,会出现这样的界面。此时游戏结束,按下窗口右上角的叉号即可关闭程序。

    在游戏过程中,如果点下退出按钮,程序会转换为这个界面。

    此时已宣告玩家不再进行游戏,按下开始按钮也不再会有效用,玩家关闭整个窗口即可。
    三、植物角色与阳光的设计本游戏含有六种植物,包括向日葵,豌豆射手,坚果,双发豌豆射手,机枪射手与樱桃炸弹。向日葵与豌豆射手,双发豌豆射手和机枪射手的生命值都为100,坚果墙的生命值为400,豌豆射手类的植物他们的射程范围都是只能达到横坐标1000以内的僵尸,每发子弹。

    以上的这张图含有六种植物的五种向日葵,坚果,豌豆射手,双发射手与机枪射手。向日葵会每隔一段时间生产出阳光,屏幕上每隔一段时间也会落下一个阳光,点击阳光后阳光消失,阳光值会增加二十五。当僵尸达到植物的攻击范围时会发出子弹,每发子弹造成数值为5的伤害。

    双发射手一次发两法豌豆子弹伤害值为10,豌豆射手一次发一发伤害值为5,机枪射手一次发五法伤害值为25。关于子弹与植物的联系,下面我要详细介绍。
    在本游戏的框架中有一个类似中枢作用的类game_view,它属于game_controller.h这个头文件。这个类包含了主要的三个QVector分别存放所有的非樱桃炸弹的植物,所有僵尸,和所有子弹。每颗子弹都是由特定的子弹生成,在本程序中子弹的坐标完全由发射它的植物决定,植物发射子弹需求信号的频率决定了子弹发射的频率。

    下面我们来介绍坚果墙,坚果墙可以阻止非撑杆跳僵尸的移动(撑杆跳僵尸可以有一次跳过植物继续移动的机会)。当坚果墙的生命值低于原有的三分之二时,它的一部分变得残破如图。当它的血量不到原来的三分之一时,坚果的缺损程度会更大。
    樱桃炸弹是本游戏另一种特殊的植物,它只要放上去就会爆炸,爆炸后会在地面产生一个难以消去的大坑,在爆炸范围内的僵尸死亡动画则是灰飞烟灭。它相较于其他植物而言,特殊之处在于它攻击范围大威力大,但是在游戏的设定中它对撑杆跳僵尸威力较小(因为撑杆跳僵尸移动较快)。
    阳光与子弹的设计相似,它的来源有两方面,一方面是向日葵每隔一段时间生成的,另一方面是从屏幕上每隔一段时间落下的阳光。阳光点击即可得到25阳光值。向日葵生成阳光的设计与豌豆射手发射子弹的设计是相似的,每隔一段时间向日葵发出产生阳光的需求,然后在scene上产生阳光。从屏幕上掉落的阳光,是战斗的scene每隔10秒发送一个startTimer(10000)需求信号,然后中枢类的 timeEvent生成阳光。
    四、僵尸的设计本游戏设计了四种僵尸,三种特殊的僵尸,包括撑杆跳僵尸,铁桶僵尸。铁桶僵尸生命值为50速度为3,,报纸老人僵尸生命值为80速度为3,普通僵尸的生命值为25速度为3,撑杆僵尸生命值为100.速度为10,撑杆僵尸跑的比其他僵尸都快。普通僵尸的被子弹打死的死亡动画为头被打掉了的gif,被樱桃炸弹炸死的动画为化为灰烬的gif。铁桶僵尸当生命值为20以上时是带着头盔的,生命值大于0但是小于20时铁桶僵尸失去头盔。

    注:此时铁桶僵尸并未失去头盔。

    注:此时铁桶僵尸失去头盔。铁桶僵尸的死亡动画适合普通僵尸是一致的。
    然后我们来介绍撑杆跳僵尸,当它拿着撑杆时它是可以遇到植物做撑杆跳的,并且樱桃炸弹炸不死它。它跳跃后他就和其它僵尸移动速度差不多了,攻击特性也和其他的一样。撑杆跳僵尸一跳可以越过一格,但是它还是有一个致命的弱点,由于它运动员的身高过于高,它可以在奔跑与跳跃的过程中被相邻行的植物射手攻击到,所以克服这种僵尸的具体策略就是在它所在行放置两个土豆将它围困在其中,在相邻行设置射手攻击起跳或奔跑时的撑杆僵尸。
    我们再来介绍报纸老头僵尸,这类僵尸的防御力比较强(因为拿着报纸),它分为三种状态。当它的生命值大于40时,它的形象是拿着报纸的老头僵尸,当它的生命值在30到40之间时它是一个带着问号的僵尸形象,报纸被击落。当它的生命值小于30时,它的形象是一个暴走的僵尸形象。
    五、小车的设计小车的设计遵从原作的设计,但也有所创新。由于本游戏的设计,撑杆跳僵尸是一个速度快生命值高的厉害角色,所以小车对于它的判断就比较特殊,只要它距离小车有两个的距离小车就会发动,其他僵尸是靠近小车三分之一格的距离才会发动。
    六、对于铲子使用的解释点击铲子时必须尽量点击铲子图标的中心处这样鼠标相应比较灵敏,点击完后铲子图标会随着鼠标移动而移动,而后只要点击相应的植物即可清除植物。另外点击右键可以使铲子回到原处。
    3  留言 2019-02-28 11:21:35
  • 基于JAVA的图书馆书库管理系统

    摘要图书馆书库管理系统主要是完成图书管理员对图书的管理(增加新书,删除旧书,并修改等的图书编辑);图书管理员对读者借还书的统计(图书的在库数目和还日期的统计)和管理;读者和管理员对图书信息和读者信息的查询;当查到所需信息时,打印出相应的信息报表等工作。
    在图书馆书库管理系统的设计与实现过程中,我深深体会到此次毕业设计的重要性———它是我走上工作岗位前的一次重要的练习,更深刻体会到理论联系实践的重要性和必要性。同时,我也感受到JAVA 和SQLSERVER 2000 的功能之强大,事件处理的灵活性和高效性。但我掌握和应用的还不是很熟练,应多加实践和练习,在以后的工作中,我将不断的学习和充实自己,力争成为一个高水平的程序员。
    关键字:JavaSwing; SQLServer ;图书馆管理;图书馆
    第1章 数据库设计1.1 逻辑设计数据库的ER图::

    Library(Category,Quantity,BooksID,BookName,Author,Edition,Storetime)Member(MembersID,StudentName,Class,StudentNumber)List(ListNumber,BookName,Author,Edition,Quantity,Bookdate,MembersID)BorrowRecord(RecordNumber,BooksID,MembersID,Borrowdate,Author,Edition,BookName)BookRecord(Storetime,Borrowtime,BookName,MembersID,StudentName)
    1.2 物理设计1.2.1 表总汇


    表名
    功能说明




    领书订单表
    根据订单领取书籍


    借书记录表
    记录借书的信息


    书籍信息表
    书库里的书籍信息


    会员表
    会员信息


    书籍记录表
    书籍的历史记录



    1.2.2 领书订单表


    表名
    领书订单(List)






    列名
    数据类型(精度范围)
    空/非空
    约束条件


    ListNumber
    int
    非空
    主键


    MembersID
    Int
    非空
    主键


    BookName
    varchar

    没有


    Author
    varchar

    没有


    Edition
    varchar

    没有


    Quantity
    varchar

    没有


    Bookdate
    datetime

    没有


    补充说明





    1.2.3 借书记录表


    表名
    借书记录(BorrowRecord)






    列名
    数据类型(精度范围)
    空/非空
    约束条件


    RecordNumber
    int
    非空
    主键


    BooksID
    int
    非空
    主键


    MembersID
    int
    非空
    主键


    Borrowdate
    varchar

    没有


    Author
    varchar

    没有


    Edition
    varchar

    没有


    BookName
    datetime

    没有


    补充说明





    1.2.3 书籍信息表


    表名
    书籍信息(Library)






    列名
    数据类型(精度范围)
    空/非空
    约束条件


    Category
    varchar

    没有


    Quantity
    int

    没有


    BooksID
    int
    非空
    主键


    BookName
    varchar

    没有


    Author
    varchar

    没有


    Edition
    varchar

    没有


    Storetime
    datetime

    没有


    补充说明





    1.2.5 会员表


    表名
    会员(Member)






    列名
    数据类型(精度范围)
    空/非空
    约束条件


    MembersID
    int
    非空
    主键


    StudentName
    varchar

    没有


    Class
    varchar

    没有


    StudentNumber
    int

    没有


    补充说明





    1.2.6 书籍记录表


    表名
    书籍信息记录(BookRecord)






    列名
    数据类型(精度范围)
    空/非空
    约束条件


    Storetime
    datetime

    没有


    Borrowtime
    datetime

    没有


    BookName
    varchar

    没有


    MembersID
    int
    非空
    主键


    StudentName
    varchar

    没有


    补充说明





    第2章 用户界面设计2.1 主界面
    2.2 采购管理系统界面订购图

    取消订购

    2.3 流通系统界面借书界面图

    还书界面图

    领书界面图

    2.4 查询系统界面查询书籍界面

    查询记录界面

    2.5 编目系统界面新书编目界面图

    更新书籍界面图

    会员注册界面图

    第3章 模块设计3.1 模块总汇3.1.1 模块总汇表


    子系统(采购管理系统)





    模块名称
    功能简述


    订购
    是学生和老师订购书籍的功能


    取消订购
    取消书籍订购


    子系统(流通管理系统)



    模块名称
    功能简述


    借书
    学生借书功能


    还书
    学生还书功能


    领取书籍
    领取订购的书籍






    子系统(查询系统)





    模块名称
    功能简述


    查找书籍
    查找书籍的信息


    查找记录
    查找书籍记录


    子系统(编目系统)



    模块名称
    功能简述


    新书编目
    把新到的书编入书库


    更新书籍
    修改书籍的存档



    3.1.2 模块关系图
    参考文献[1] 张海藩. 软件工程导论(第四版). 北京:清华大学出版社
    [2] 耿祥义,张跃平. Java2实用教程(修订). 北京:清华大学出版
    [3]萨师煊,王珊. 数据库系统概论(第三版). 北京:高等教育出版社
    [4]Rob Hawthorne. SQL SERVER 2000从零开始(第一版). 北京:人民邮电出版
    0  留言 2019-01-21 10:09:55
  • 基于JAVA和ACCESS的综合测评系统(服务端和客户端)

    摘 要大学期间,综合测评计算是每学期必不可少的工作。人工计算综合测评是一个很繁杂的过程:每个学生先计算自己的综合测评成绩,制成草表,上交给班委;然后班委核对并将成绩录入制成电子文档上交给院系相关部门。在这个过程中,学生常常感到厌烦,因而草表的准确率很低;接着人工核对、录入成绩,造成工作量大,效率低下,准确率也无法得到保证。所以,广大师生迫切希望信息化综合测评系统的产生。利用该系统,同学们可以方便准确地计算出自己的综合测评成绩,并能将结果上传至服务器,省去班委人工核对、成绩录入这些烦琐的工作。而且,系统提供的查询功能可以方便同学们对自己所需信息的检索。该论文主要介绍了网络上最受欢迎的Java Applet技术、系统的分析设计、各个功能模块的实现、系统的测试调试、以及系统开发过程中遇到的问题和问题的解决。
    关键词:综合测评;计算;查询;Applet
    1 综合测评系统分析设计1.1 需求分析根据计算机科学与工程系综合测评评分细则以及广大同学计算综合测评的经历,整理得到该系统的功能需求为:

    用户只要根据列出的得分项进行选择,以及少量的数据输入就可以计算出自己的综合测评成绩
    用户将自己计算好并核对过的综合测评成绩上传,为防止恶意用户随意修改合法用户的成绩,成绩上传前必须进行用户合法性的验证,合法用户方能将自己的综合测评成绩上传至服务器端的数据库。同时,合法用户也可以随时修改自己的密码
    用户可以根据自己的需要进行查询:

    输入学号,就可以精确得到该位同学的综合测评的得分、排名等情况查询所有学生的综合测评得分情况,并按学号顺序排列显示查询业务学习成绩大于等于或小于某一值的所有学生的综合测评得分情况,并按业务学习成绩从高到低排列显示查询综合测评成绩大于等于或小于某一值的所有学生的综合测评得分情况,并按综合测评成绩从高到低排列显示查询业务学习成绩大于或小于某一值且综合测评成绩大于等于或小于某一值的所有学生的综合测评得分情况,并按学号的顺序排列显示
    用户可以查看全班同学的业务学习成绩及综合测评成绩各个得分段的比例,更好地了解班级的综合测评情况

    1.2 系统整体框架根据系统的功能需求,分析出系统的框架为:

    1.3 模块功能说明1.3.1 政治素质该模块能够将所有的政治素质方面的得分项列出来,供用户选择自己的得分情况,然后计算出政治素质的得分。法纪观念、学习态度、品德修养、劳动实践、奖惩得分与政治素质模块的功能相似,都是计算各自的得分,所以在此不一一阐述。
    1.3.2 政治思想素质该模块则将政治素质、法纪观念、学习态度、品德修养、劳动实践、奖惩分各个模块组合,以整体的方式显示给用户,并能将各个小模块的得分情况相加,得出政治思想素质的实际得分(100分制)及总得分(实际得分×20%)
    1.3.3 业务学习得分该模块能够处理用户输入各门课程的得分情况,计算业务学习实际得分(100分制,业务学习实际得分=各门课程的学分成绩总和÷各门课程学分总和+公共选修课的成绩)及总得分(业务学习实际得分×60%)。
    1.3.4 智能素质得分该模块则将科研能力、社会工作能力、师范生技能、文艺活动能力各个小模块的得分相加得到智能素质的实际得分(100分制)及总得分(实际得分×10%)。
    1.3.5 体育素质得分该模块能够处理用户体育课成绩的输入,计算体育素质的实际得分(体育课成绩×60% + 课外体育活动成绩)及总得分(实际得分×10%)。
    1.3.6 精确查询该模块能够接受用户输入学号,查询该同学综合测评的相关情况。
    1.3.7 模糊查询该模块能够接受用户的输入,根据用户的需要,以业务学习得分和综合测评得分为条件进行查询。
    1.3.8 综合测评成绩比例显示该模块能够根据全部上传的综合测评,统计总人数,某一分数段的人数,然后按比例图显示给用户。
    1.3.9 综合测评成绩上传该模块能够验证用户的合法性并将合法用户计算出的综合测评得分情况上传至服务器端的数据库上,作为留档材料,也作为成绩核对的依据。
    1.3.10 用户密码修改该模块能够验证用户的合法性并能实现合法用户对自己密码的修改。
    2 综合测评系统实现2.1 系统数据库设计数据库需求分析
    本系统数据库的设计总体需求是:学号、用户密码、课程名称、课程学分、成绩类型、政治思想素质、业务学习、智能素质、体育素质、综合测评得分、备注。
    本系统采用ACCESS作为数据库
    在本系统中,要求数据库名为:综合测评数据库.mdf,并在里面建立系统设计时需要用到的数据表,各表设计如下所示:
    用户信息表



    字段名称
    数据类型
    字段大小
    允许空




    学号
    文本
    15



    姓名
    文本
    15



    密码
    文本
    20




    其中:学号为主键
    综合测评成绩表



    字段名称
    数据类型
    字段大小
    允许空
    小数位数




    学号
    文本
    50




    政治思想素质
    数字
    单精度型
    允许
    2


    业务学习
    数字
    单精度型
    允许
    2


    智能素质
    数字
    单精度型
    允许
    2


    体育素质
    数字
    单精度型
    允许
    2


    综合测评得分
    数字
    单精度型
    允许
    2


    备注
    备注

    允许



    其中:学号为主键。
    课程信息表



    字段名称
    数据类型
    字段大小
    允许空




    课程名称
    文本
    20



    学分
    文本
    10



    成绩类型
    文本
    10




    其中:课程名称为主键。
    业务学习成绩表



    字段名称
    数据类型
    字段大小
    允许空




    学号
    文本
    20



    备注
    备注





    说明:其中学号为主键,本表的各个字段除了学号与备注这两个固定字段以外,其他字段都是在程序运行过程中动态生成的。
    2.2 数据库访问模块的实现本项目与数据库的连接采用JDBC-ODBC桥连接[8],其连接成功后将出现提示,如下图所示界面:

    其核心代码如下:
    boolean success=true; //定义一个标志变量标志连接数据库是否成功try{ Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //加载驱动程序 con=DriverManager.getConnection("jdbc:odbc:zonghecepingshujuku"); //与数据库的连接 stmt=con.createStatement(); //执行访问数据库的SQL语句 }catch(Exception e){ JOptionPane.showMessageDialog(this, "数据库连接失败!"); success=false;}if(success){ JOptionPane.showMessageDialog(this,"数据库连接成功"); }
    2.3 客户端各个模块的实现2.3.1 政治思想素质模块的实现本模块的界面主要是利用Java的awt包及swing包开发的,界面实现如下图所示:

    本模块是由政治素质、法纪观念、学习态度、品德修养、劳动实践、奖惩得分,其他得分共七个小模块够成的,各小模块的容器面板都是继承自swing包的Jpanel,而且其中的各个元素,如:复选框、文本框等采用GridLayout布局管理。各个小模块作为一个类来设计,其中包含构造函数,getscore()方法及getbeizhu()方法,分别取得本小模块的得分,及得分的原因。选取其中的政治素质模块描述其实现过程(其他模块类似)如下:
    class Zhengzhisuzhi extends Zuhemianban //政治素质类,详见源代码{ …… //类内部成员的声明 public Zhengzhisuzhi(){ …… } //构造函数,实现界面的布局 public float getscore() //获取政治素质得分 { beizhu=""; //用于存放得分理由 float score=18; //基本分18分 if(this.malie.getState()) //如果“马列理论学习优”有选中 { score+=1; //加上该项的得分 beizhu+=this.malie.getLabel()+";"; //得分理由加入备注字符串中 } …… //其他得分项类似处理 return score; //将得分值返回 } public String getbeizhu() //获取备注内容 { return beizhu; }}
    2.3.2 业务学习成绩计算模块业务学习成绩的界面如下图所示:

    其中一个科目就是一个小模块,而且这些科目的信息是从服务器端的“课程信息表”中获取的,这些科目组合就够成了业务学习成绩计算的主要部分。但由于这些科目是动态生成的,而不是设计时给定的,所以必须用一个数组链表存储这些动态生成的科目类实例,才可能在计算出业务学习得分的过程中得到必须的数据。也因其是动态生成的,所以实现过程相对比较复杂,其核心代码如下:
    public Yewuxuexi (InetAddress ip) //构造函数传入服务器的IP地址{ …… //建立与服务器通信的数据输入输出流,并提交初始化请求 xinxis=datain.readUTF().split(":"); //读取初始化数据 for(int i=1;i<xinxis.length;i++) { String[] kechengxinxi=xinxis[i].split(","); Xuexichengji xuexichengji=new Xuexichengji(kechengxinxi[0], Float.parseFloat(kechengxinxi[1].trim()),kechengxinxi[2]);//实例化一门科目,并将其加入面板中 this.add(xuexichengji);//将其加入数组链表中,为下面计算课程的学分成绩提供数据 this.arraylist.add(xuexichengji); } //for} //Yewuxuexipublic float getscore() //获取各门课程的学分成绩总和{ float sum=0; //初始化成绩为0 for(int i=0;i<this.arraylist.size();i++) { //遍历链表中的每个元素,并将得分累加 sum=sum+((Xuexichengji)(arraylist.get(i))).getscore(); } return sum; //将得分作为该方法的返回值返回}
    2.3.3 智能素质模块智能素质的模块实现界面如下图所示:

    该模块是由科研能力、社会工作能力、师范生技能、文艺活动能力、其他得分5个小模块组合成的,其实现过程与政治思想素质的实现过程类似,这里不再赘述。
    2.3.4 体育素质模块体育素质模块实现界面如下图所示:

    本模块实现过程与政治思想素质的实现过程也类似,这里不再赘述。
    2.3.5 成绩上传模块成绩上传模块的实现界面如下图所示:

    该模块类继承自java.awt包中的Frame类,当用户输入的学号与密码正确时,才能将成绩上传,其实现的核心代码如下:
    //综合测评得分情况插入数据库的SQL语句 strshangchuan=strshangchuan + "insert into 综合测评成绩表 values('" +this.xuehao.getText().trim()+"'," + this.sqlzongheceping + ")"; String[] temps=this.yewuxuexi.split(":"); //业务学习得分情况插入数据库的SQL语句 String temp=":insert into 业务学习成绩表(学号,备注" +temps[0] +") values('" +this.xuehao.getText().trim()+"','"+temps[2] +"'" + temps[1]+ ")"; strshangchuan+=temp;
    2.3.6 用户密码修改模块用户密码修改模块的实现界面如下图所示:

    该模块类也是继承自java.awt包中的的Frame类。首先将进行“新口令”与“确认新口令”的核对,如果两者相同,将进行用户合法性检查。如果是合法用户,可进行密码修改,数据库信息修改成功后,将反馈一个“密码修改成功”的消息给用户。否则,不能进行密码的修改,将反馈一个“密码修改失败”的信息给用户。其中,用户合法性的检查与成绩上传时用户的合法性检查一致,这里不再赘述,只取其中部分核心代码说明如下:
    if(datain.readUTF().trim().equals("密码修改合法用户")) //若是合法用户{ //密码修改SQL语句 String xinmimashangchuan="update 用户信息表 set 密码='"+this.xinkouling.getText().trim()+"'where 学号='"+this.xuehao.getText().trim()+"'"; dataout.writeUTF(xinmimashangchuan); //更新数据库请求上传}else //非法用户{……}
    2.3.7 查询模块查询模块实现界面如下图所示:

    其分为精确查询与模糊查询两块,精确查询是将输入的学号作为查询条件,而模糊查询则根据业务学习成绩与综合测评成绩的组合作为查询条件进行查询。精确查询的结果将返回个人的各个得分情况及综合测评与业务学习成绩的排名情况。模糊查询返回结果的界面下图所示:

    当业务学习成绩与综合测评成绩选项数值都为0时,或者两个选项的值都不为0时,将返回所有结果集,并按学号顺序排列。当业务学习选项的数值为0但综合测评成绩选项数值不为0时,或者相反时,将以非0的一项作为排列显示的依据。其核心代码如下:
    精确查询
    resultset= stmt.executeQuery("select * from 综合测评成绩表 order by 综合测评得分 desc"); //成绩由高到低排列while(this.resultset.next()) //检索该生的综合测评记录{ i++; //i标记该学生综合测评成绩的排名 if(this.resultset.getString(1).equals(xinxis[1].trim())) //若是该学生的综合测评成绩记录则提取其所有的得分情况及排名 { jieguo+=","+this.resultset.getFloat(2) + "," + this.resultset.getFloat(3)+","+this.resultset.getFloat(4) + "," + this.resultset.getFloat(5)+","+this.resultset.getFloat(6) + "," + i; break; //跳出检索 }}
    模糊查询
    String mohuchaxunjieguo=datain.readUTF(); //读取模糊查询结果 //以下是数据在JTable中的显示this.vector.removeAllElements(); //将存放显示数据的向量清空this.tm.fireTableStructureChanged(); //通知所有侦听器表结构已更改。String[] strmohuxianshis=mohuchaxunjieguo.split(":");//将从服务器端返回的数据字符串按行分割 for(int i=1;i<strmohuxianshis.length;i++) { Vector rowvector=new Vector(); String[] strs=strmohuxianshis[i].split(","); for(int j=0;j<strs.length;j++) { rowvector.addElement(strs[j]); } //添加一个显示数据项 this.vector.addElement(rowvector); //添加一行显示数据项 } this.tm.fireTableStructureChanged();
    2.3.8 成绩比例图显示模块该模块实现界面如下图所示:

    其中,左右两块为同一类的两个不同实例化对象。该模块的实现过程是:
    先查询数据库,统计总人数以及各个成绩段的人数,然后在客户端计算各个成绩段人数所占总人数的比例,最后将比例图通过Graphics类的fillArc()方法画出,数据通过文本框显示出来,其核心代码如下:
    public void paint(Graphics g){ int int_red=(int)(bili[0]*360); //计算红色扇形圆心角的度数 int int_green=(int)(bili[1]*360); //计算绿色扇形圆心角的度数 int int_blue=(int)(bili[2]*360); //计算蓝色扇形圆心角的度数 int int_yellow=360-int_red-int_green-int_blue; //计算黄色扇形圆心角的度数,下面画出比例图 g.setColor(Color.red); //绘制红色扇形 g.fillArc(startx,starty,endlen,endlen,0,int_red); g.setColor(Color.green); //绘制绿色扇形 g.fillArc(startx,starty,endlen,endlen,int_red,int_green); g.setColor(Color.blue); //绘制蓝色扇形 g.fillArc(startx,starty,endlen,endlen,int_red+int_green,int_blue); g.setColor(Color.yellow); //绘制黄色扇形 g.fillArc(startx,starty,endlen,endlen,int_red+int_green+int_blue,int_yellow);}
    参考文献[1] 邓良松,刘海岩,陆丽娜.软件工程.[M].西安:西安电子科技大学出版社
    [2] 解圣庆.Access2003数据库教程.[M].北京:北京大学出版
    [3] 李佳范,俊弟,邓剑民 .Access 2003数据库应用.[M].北京:人民邮电出版社
    [4] 电脑知识网.[网页]http://www.92bmw.com/Article/Folder6/Java/2007318/9743.Html
    [5] 汪晓平,俞俊,李功.精通java网络编程. [M].北京:清华大学出版社
    0  留言 2018-12-24 11:06:27
  • 基于C++实现的双调排序算法

    1 算法描述双调排序的基本概念有两个:双调序列和 Batcher 定理。
    双调序列:双调序列是由两个单调性相反的非严格单调序列构成的序列(非严格指的是可以出现重复元素,或者NaN不参与排序)。比如(23, 10, 8, 3, 5, 7, 7, 8)。当序列满足以下两种情况时,它是双调序列:

    存在一个ak(1 ≤ k ≤ n),使得a1 ≥..≥ ak ≤..≤ an成立。
    序列能偶循环位移满足条件1

    Batcher 定理:将任意一个长为 2n 的双调序列 A 分为等长的两半 X 和 Y,将 X 中的元素与 Y 中的元素一一按原序比较,即a[i]与a[i + n] (i < n)比较,将较大者放入 MAX 序列,较小者放入 MIN 序列。则得到的 MAX 和 MIN 序列仍然是双调序列,并且 MAX 序列中的任意一个元素不小于MIN 序列中的任意一个元素。
    读过( https://blog.csdn.net/u014226072/article/details/56840243 )和( https://blog.csdn.net/hanshuning/article/details/49132089 )两位笔者的代码和思路后,总结算法基本过程主要有两步,首先将输入的无序的序列转化成双调序列,然后将得到的双调序列进行双调合并即可得到最终解。
    具体思路:对于任意两个元素x,y,无论x ≥ y 或 x ≤ y,序列(x,y)均为双调序列。因此任何无序的序列都是由若干个二元有序的双调序列连接而成的。于是,对于一个无序序列我们按照递增和递减顺序合并相邻的双调序列,按照双调序列的定义,通过连接递增和递减序列得到的序列是双调的。最终,我们可以将若干个只有 2 个元素的双调序列合并成 1 个有 n 个元素的双调序列。

    因为思路基本相同,我在( https://blog.csdn.net/hanshuning/article/details/49132089 )笔者分享的代码上略加修改形成了第一版代码(主要函数):
    void segmentedBitonicSort(float* data, int* seg_id, int* seg_start, int n, int m) { //判断输入是否有误 if (n <= 0 || m <= 0 || m>n) { cout << "Input error!n>m>0" << endl; return; } if (!(seg_start[m] == n && seg_id[n - 1] == (m - 1))) { cout << "Input error! seg_start[m]==n,seg_id[n-1]==(m-1)" << endl; return; } //先段内排序 for (int d = 0; d<m; d++) { int len = 1; //seg_start[d+1]-seg_start[d]为此段长度 while (len < seg_start[d + 1] - seg_start[d])//循环退出的条件 len = len << 1;//寻找大于n的最小的2的幂次方len float Max = 999999;//作为填充数 //vector<float> segdata(len); int _properly_divided = 1;//判断是否整出的参量 int _real_length = (seg_start[d + 1] - seg_start[d]); vector<float> segdata(len); for (int i = 0; i < seg_start[d + 1] - seg_start[d]; i++) { segdata[i] = data[seg_start[d] + i]; } //如果len > n,就说明数组的个数不够,要将个数填充到len个 for (int i = seg_start[d + 1] - seg_start[d]; i < len; i++) segdata[i] = Max; ///////对整个数组进行排序 for (int step = 2; step <= len; step <<= 1) { //////内部循环可任意交换 for (int i = 0; i < len; i += step << 1)//1 { ///前半部分升序排 for (int step0 = step >> 1; step0 >0; step0 >>= 1)// 2 { for (int j = 0; j < step; j += step0 << 1)//3 { for (int k = 0; k < step0; ++k)//4 { if (segdata[i + j + k] > segdata[i + j + k + step0] || segdata[i + j + k] != segdata[i + j + k]) //交换数据使升序排列,同时判断二者之中是否有NaN { //交换data float T = segdata[i + j + k]; segdata[i + j + k] = segdata[i + j + k + step0]; segdata[i + j + k + step0] = T; } } } } //后半部分降序排 if (i + step < len) { //////内部循环可任意交换 for (int step0 = step >> 1; step0 >0; step0 >>= 1) //1 { for (int j = 0; j < step; j += step0 << 1) //2 { for (int k = 0; k < step0; ++k) //3 { if (segdata[i + step + j + k] < segdata[i + step + j + step0 + k] || segdata[i + step + j + step0 + k] != segdata[i + step + j + step0 + k]) //交换数据使降序排列,同时判断二者之中是否有NaN { //交换data float T = segdata[i + step + j + k]; segdata[i + step + j + k] = segdata[i + step + j + k + step0]; segdata[i + step + j + k + step0] = T; } } } } } } } //赋值 for (int i = seg_start[d]; i < seg_start[d + 1]; i++) { data[i] = segdata[i - seg_start[d]]; if (data[i] == Max) data[i] = sqrt(-1.f); } }}
    经测试,代码运行正确。然而这段代码在解决序列长度非 2 的 n(n 自然数)次幂时,利用了补无穷的思想。实际需要的数组长度大于输入的数组长度,因此借助了 C++ STL工具类\<vector\> 动态的分配了数组大小,不能满足内存高效的挑战要求。
    vector<float> segdata(len);for(int i = 0; i < seg_start[d+1]-seg_start[d]; i++){ segdata[i] = data[seg_start[d] + i];}// 如果len>n, 就说明数组的个数不够, 要将个数填充到len个for(int i = seg_start[d+1] - seg_start[d]; i < len; i++) segdata[i] = Max;
    经过很长时间的思考,我发现无法在这种方法的基础上避免动态分配内存。在网上查阅资料后,在简书中发现了一篇文章( https://www.jianshu.com/p/ea4a62fdaae9 )。

    简单的概括就是利用多次分段的排序和归并以达到整体排序。因此,我推倒第一版代码重新开始编写。将输入分为标准(指序列长度为 2 的 n 次幂)和非标准两种情况。标准情况直接求解,非标准情况以小于序列长度的最大的 2 的幂次方(记作len)作为参考将输入序列分为前后两部分,通过三次排序运算求解。(源码见附件)
    所有挑战均尝试并完成

    不递归:segmentedBitonicSort函数中不进行任何直接或间接递归
    不调用函数:segmentedBitonicSort函数中不调用任何除标准库函数以外的任何其他函数
    内存高效:算法中所有的数值交换均在初始数据数组中完成,没有任何动态分配以及使用 STL 类
    可并行:排序算法中所有 for 循环头嵌套时没有任何上下依赖关系,因此 for 循环内部的循环顺序可以随意改变
    不需内存:segmentedBitonicSort函数没有调用任何函数,不使用全局变量,所有局部变量均是 int,float 或指针型,没有使用 new 关键字
    绝对鲁棒:输入数据包含NaN时不影响其他数据排序,且NaN个数不变。通过判断 NaN! = NaN 实现

    测试数据
    float data[13] = { 2,sqrt(-1.f) - 100 , 1, 100, 4, 0.5,sqrt(-1.f), sqrt(-1.f), 0.5, 2, 0.1, 2, 5 }; int seg_id[13] = { 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4}; int seg_start[6] = { 0,3,5,9,12,13}; int n = 13; int m = 5;

    float data[11] = { 0,sqrt(-1.f) - 100 , 2, 100, 4, 0.5,sqrt(-1.f), sqrt(-1.f), 3, 0.1, 2 }; int seg_id[11] = { 0, 0, 0, 1, 1, 2, 2, 2, 2,3,3 }; int seg_start[5] = { 0,3,5,9,11 }; int n = 11; int m = 4;

    float data[10] = { 0,sqrt(-1.f) - 100 , 2, 100, 4, 0.5, sqrt(-1.f), 3, 0.1, 2 }; int seg_id[10] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 2 }; int seg_start[4] = { 0,3,6,10 }; int n = 10; int m = 3;

    性能分析
    时间复杂度:如果以串行方式运行,其复杂度为Ο(nlog2n)相对的,如果有n个可同时运行的线程,复杂度为Ο(log2n)。
    本程序中未使用递归,所以更节省时间和空间。内存高效,没有调用任何函数(包括C/C++标准库函数),没有使用全局变量,没有进行动态内存分配。可并行,segmentedBitonicSort涉及到的所有时间复杂度 O(n)以上的代码都写在 for 循 环中,而且每个这样的 for 循环内部的循环顺序可以任意改变,不影响程序结果。可以处理任意长度的输入序列。绝对鲁棒,在输入数据中包含NaN时(例如 sqrt(-1.f)),把NaN当作比任意数大的数进行排序,保证除NaN以外 的数据正确排序,NaN的个数保持不变。
    不足

    算法复杂度较高,执行效率低
    时间仓促,代码有可精简之处
    初始化变量写死在文件中,用户调试体验较差
    1  留言 2018-11-06 15:26:28
  • 基于C++实现的自动化工具及词法语法分析程序

    1 实验目的
    了解词法分析过程的基本思想
    体会词法分析器及其自动化生成工具的开发过程
    了解语法分析过程的基本思想
    体会语法分析器及其自动化生成工具的开发过程

    2 实验内容及要求2.1 自动生成工具要求
    能够根据文法自动生成词法分析程序
    能够根据文法自动生成语法分析程序

    2.2 词法分析器设计要求
    输入正规文法或者正规式,经过NFA到DFA的转换,DFA最小化,递归下降法生成程序等步骤,输出能识别文法表示的句子词法分析程序
    要求至少支持科学计数法常量和标识符识别
    根据输入字符串输出Token串。如果是非法字符串则输出错误信息

    2.3 语法分析器设计要求
    要求使用LL(1)方法,算符优先分析方法,LR(1)三种方法之一设计语法分析程序
    输入上下文无关文法,输出能进行语法分析的程序
    输入待检测的Token串,输出检测结果和出错信息

    3 实验步骤3.1 设计词法自动生成工具myLex3.1.1 输入输出说明输入
    VN1 VT2 VN3VN4 VT5 VN6.....第一个VN为开始符号如S->bA 则为 S b A如S->a 则为 S a NULL如S->NULL 则为 S NULL NULL最多为26个状态
    输出
    点击G_to_NFA.exe ,NFA_to_DFA.exe ,Min_DFA.exe,得到代码文件test.cpp
    3.1.2 程序流程图myLex程序流程图如图1所示:

    3.1.3 程序文件截图myLex程序文件截图如图2所示:

    3.2 设计语法自动生成工具myYacc3.2.1 实现原理
    读入文法进行标记1,2,3,4……(如何记录每一项用字符串解决)
    写First函数
    写First_str() 入口参数是字符串
    保存项目集,并编写CLOSURE(I)函数
    GO(I, X)函数,检测集合是否出现过,并生成图 (字符串比较)
    设计分析表的数据结构 (矩阵,负的为ri,正的为Si,acc=140406为接受态)
    根据对应的图,遍历节点,填写相应的表(结合在Go函数中)
    写分析的流程,根据分析表分析,返回是否正确
    自动生成代码:总结自己写的过程,找出变得和不变的,用代码实现

    3.2.2 输入输出说明输入
    g.txt中输入拓广文法(Z代替S',$表示空)例如 S->aABd的话记为SaABdZSBaBSBBBb
    输出
    点击myYacc,输出代码文件test2.cpp
    3.3 程序流程图myYacc程序流程图如图3所示:

    3.4 程序文件截图myYacc程序文件截图如图4所示:

    3.5 设计词法分析程序3.5.1 实现原理在词法分析中,利用空格,tab键,换行,运算符进行分隔,获得字符串,对于简单的字符串可以在主程序中处理,对于复杂的字符串,可以将字符串用myLex自动生成的代码进行检测。
    3.5.2 输入输出说明输入
    字符序列string字符串
    输出
    输出格式:二元式序列(类型,值)
    程序流程图
    词法分析程序流程图如图5所示:

    程序文件截图
    词法分析程序文件截图如图6所示:

    3.6 设计语法分析程序3.6.1 实现原理在语法分析中,利用空分号进行分隔,获得处理的token串,然后根据文法将每个token串换处成文法能处理的字符串,用myYacc自动生成的代码进行检测。
    3.6.2 输入输出说明输入
    token 串
    输出
    yes 或 error,错误情况将输出token串中出错的位置。
    程序流程图
    语法分析程序流程图如图7所示:

    程序文件截图
    语法分析程序文件截图如图8所示:

    4 实验结果4.1 词法自动生成工具myLex测试4.1.1 科学计数法输入文法
    S d AS . BS e CA d A A . BA e CA NULL NULLB d DD e CD d DD NULL NULLC d EC s FF d EE d EE NULL NULL
    依次点击演示1自动生成工具\myLex\tool中的G_to_NFA.exe ,NFA_to_DFA.exe ,Min_DFA.exe,得到代码文件test.cpp。将其中的str[index]==’d’替换成str[index]>=’0’ && str[index]<=’9’,将其中的str[index]==’s’替换成str[index]==’+’||str[index]==’-‘,编译得到可执行程序。
    在in.txt中输入:
    3.14e103.14e+103.14e-10314e+10314+10.14e12e10
    程序输出

    4.1.2 标识符输入文法
    S l NULLS l AA l NULLA d NULLA l AA d A
    依次点击演示1自动生成工具\myLex\tool中的G_to_NFA.exe ,NFA_to_DFA.exe ,Min_DFA.exe,得到代码文件test.cpp。将其中的str[index]==’d’替换成str[index]>=’0’ && str[index]<=’9’,将其中的str[index]==’l’替换成str[index]>=’a’ && str[index]<=’z’,编译得到可执行程序。
    在in.txt中输入
    abca12sd1231abas+as2
    程序输出

    4.2 语法自动生成工具myYacc测试4.2.1 四则运算输入文法
    ZEEE+TETTT*FTFF(E)Fi
    点击演示1自动生成工具\myYacc\tool中的myYacc.exe ,得到代码文件test2.cpp,编译得到可执行程序。
    在in.txt中输入
    i+ii+(i*i)i+i*)(ii*i+(i*(i+i))
    程序输出

    4.2.2 书P135文法输入文法
    ZEEaAEbBAcAAdBcBBd
    点击演示1自动生成工具\myYacc\tool中的myYacc.exe ,得到代码文件test2.cpp,编译得到可执行程序。
    在in.txt中输入
    bccdbcdbdc
    程序输出

    4.2.3 书P165文法输入文法
    ZAAaAdAaAbA$
    点击演示1自动生成工具\myYacc\tool中的myYacc.exe ,得到代码文件test2.cpp,编译得到可执行程序。
    在in.txt中输入
    ababaababa
    程序输出

    4.3 词法分析程序测试4.3.1 测试代码/* 以下是测试程序*/int main(){ int x1,x2,x3; //变量声明 int y=0; /*变量声明 并且赋值*/ double xyz=3.14e+5; y=4+x1-(1-x2+y)/3*y; /*算数表达式*/ if(y>=0){ /*条件语句*/ x1=100; } return 0;}
    4.3.2 输出截屏
    4.4 语法分析程序测试4.4.1 测试源代码/* 测试程序*/ double y; //变量定义语句 y=3.1415e-10; //变量赋值语句 double z;//变量定义语句 float a; a=12312; a=3.1e+5; a=.123e-2; a=4+(a-(1*a+y)/3)*y; z=(x1-3)*(4-y);//变量赋值语句 if(y>=z)//if语句 if(z<=y) z=y; while((z+y*15-7)>10)//while语句 if(z<y) z=z-100;
    4.4.2 输入token流输入格式: 序号 类型 值
    1 1 double2 2 y3 5 ;4 2 y5 4 =6 3 3.1415e-107 5 ;8 1 double9 2 z10 5 ;11 1 float12 2 a......
    4.4.3 输出截屏正确时

    将a=4+(a-(1*a+y)/3)*y;改为a=4+(a-1*a+y)/3)*y;

    将z=y;改为z<=y;

    将a=12312;去掉分号

    将double z;改为dble z;

    5 实验总结5.1 完成的工作
    设计要检测的语言
    设计和编写词法分析自动生成工具myLex
    设计和编写语法分析自动生成工具myYacc
    设计和编写词法分析程序
    设计和编写语法分析程序

    5.2 收获与体会通过这次课设,我了解了词法分析过程的基本思想,体会了词法分析器及其自动化生成工具的开发过程,了解了语法分析过程的基本思想,体会了语法分析器及其自动化生成工具的开发过程。此外我还提高了编写和调试程序的能力,收获很大。最后感谢老师的悉心教导。
    2  留言 2018-11-06 15:23:56
  • 基于汇编语言的多任务飞机大战游戏

    一 需求分析系统所具备的功能包括:

    飞机游戏

    击落敌机游戏结束游戏暂停游戏胜利
    音乐播放器

    音乐暂停音乐开始
    中断调度设计处理

    采用轮转的方式进行任务的调度采用软中断的方式来进行轮转用PCB块来保存任务的上下文在中断处理函数中切换中断上下文
    系统能够实现对多个任务的管理,在调度方面采用时间片轮转的方式进行多个任务的调度;或者是在调度方面采用时钟中断的方式对多个任务进行切换,并且任务切换后,能够对任务的上下文信息进行保存
    多个任务进行切换,如果当前任务是飞机游戏时,按左右键飞机会向左向右移动并发射子弹,当子弹打中敌机时,歼灭敌机;只有将全部的敌机通通歼灭才能获得胜利,否则游戏game over。选用软件中断的方式切换到音乐播放器的任务时或者飞机游戏

    二 程序设计2.1 设计内容
    设计任务管理系统,对多个任务(任务数量≥2)进行管理和调度,能够实现任务之间的切换、保存上下文信息
    任务数量有两个分别是飞机游戏和音乐播放
    采用分屏的方式显示运行结果
    采用轮转的方式进行任务调度
    采用软件中断的方式进行任务切换,并且对内存指针指令的管理,实现上下文信息的保存与切换

    2.2 系统结构
    2.3 游戏模块流程

    2.4 中断处理流程
    2.5 音乐播放流程
    三 程序实现3.1 功能模块实现3.1.1 中断处理模块PCB与进程表
    我们用数组(而不是链表)来实现进程表,进程表含若干PCB(ProcessControl 部分段寄存器,用PUSH指令一个个压入栈。
    PCB dw 0 ; ES || 部分段寄存器,用PUSH指令一个个压入栈 dw 0 ; DS / dw 0 ; DI \ dw 0 ; SI | 指针寄存器 \ dw 0 ; BP | | dw 0 ; SP / | 通用寄存器,用PUSHA指令一起压入栈 dw 0 ; BX \ | dw 0 ; DX | 数据寄存器 / dw 0 ; CX | dw 0 ; AX / dw 0 ; IP 指令指针寄存器 \ dw 0 ; CS 代码段寄存器 | 中断时由CPU压入栈 dw 0 ; Flags 标志寄存器 / dw 0 ; SS 堆栈段寄存器,手工赋值 dw 1 ; ID 进程ID Dw 0; 0是可以调度的,1是不可以调度的3.1.2 中断处理在实模式下,x86处理器在中断发生时执行如下操作:

    将标志寄存器FLAGS值压入栈
    先后将CS和IP寄存器中的当前值压入栈
    清除标志寄存器FLAGS中的IF(中断允许标志)标志以禁止中断
    清除标志寄存器EFLAGS中的TF(陷阱标志/单步调试)、RF([调试]恢复标志) 和AC(对齐检测标志)标志
    转换程序控制到IVT指定的位置

    3.1.3 复制数据块我们PCB中的14个寄存器值,现在有13个在当前进程的栈中(另外一个是栈段寄存器SS)。我们安排在内核的调度函数schedule中,将这些寄存器值复制到进程表的对应PCB中。使用的是(功能为内存块复制的)重复字串传送指令REP MOVSW(以CX为计数值),它将DS:SI处的字传送到ES:DI处,并SI+=2、DI+=2、CX—,直到CX=0。
    3.1.4 恢复上下文因为恢复上下文寄存器,和栈切换,以及进程切换的准备操作,是交错进行的,所以程序的逻辑有些复杂,我们先尽可能多地恢复寄存器的值,再进行栈切换。但是将还需要使用到的DS先不恢复,而是在栈切换完成后,先压入新进程栈中,等以后切换进程前再弹出。IP和CS也从PCB中取出后压入新进程的栈中。在这些操作中还需使用一个寄存器,我们用的是SI,也需要先从PCB中取出压入新进程栈中,等最后一刻才恢复。
    3.2 飞机游戏模块
    绘制屏幕

    使用显示器与内存的映射关系,给内存写数据,然后显示到屏幕上
    绘制敌机

    采用重力下降的方法来降落一个飞机
    本机的方向的捕获

    使用BIOS中断来捕获键盘的事件,然后将方向存放到变量中,通过变量的值来判断方向在那里
    是否调度音乐

    通过给PCB块赋值,在中断处理函数中判断
    敌机是否存活

    使用变量来判断敌机是否死亡

    3.3 音乐播放模块音乐播放模块,顾名思义就是对音乐播放进行处理的模块。该模块通过对8255和8253对应接口赋予相应的值让其发声,实现了音乐的发声、暂停、结束、以及关闭扬声器的功能。
    通过在8253中的42端口送入一个控制字0b6h,对定时器2进行初始化,使定时器2准备接受计数初值。当把输出端口61h的PB0和PB1两位置1时发声。
    四 运行测试按q键为暂停音乐,只显示飞机游戏的任务。再次按下w音乐继续播放。在飞机游戏中,按a键为暂停飞机游戏,只显示音乐的任务。s键来恢复飞机的任务。Z键来结束所有的任务,但是在只放音乐时,不能终止所有的任务。




    3  留言 2018-11-03 16:50:46
  • 基于Filter-Hook Driver的包过滤网络防火墙系统设计与实现

    摘 要随着病毒、木马、黑客攻击等问题的出现,网络安全形势日渐严峻,网络安全产品也被人们重视起来。防火墙作为最早出现的网络安全产品和使用量最大的安全产品,也受到用户和研发机构的青睐。防火墙放置在外部网络与计算机之间作为隔离设备,可以识别并屏蔽非法请求,有效防止跨越权限的数据访问。
    本文先介绍了个人防火墙开发的研究现状、VC++6.0和MFC程序的一些技术特点,然后对基于包过滤个人防火墙的开发进行了详细的介绍和描述。通过本文可以清楚地看到一个普通个人防火墙的开发过程。本防火墙中,用户可以自行设定过滤规则,以达到对不同源和不同目标的IP地址、端口和协议的过滤。允许用户将当前规则保存为*.rul的文件格式,供下次使用时直接导入。
    本防火墙由以下几个模块组成:过滤规则添加模块,过滤规则显示模块,过滤规则存储模块,文件储存模块,安装卸载规则模块,IP封包过滤驱动功能模块。用户只需要通过主界面菜单和按钮就可以灵活地操作防火墙,有效地保护Windows系统的安全。
    关键词:个人防火墙,包过滤,网络安全,MFC
    AbstractWith the development of the Internet, security control equipment must be installed to ensure safety when the network involves a different level of trust. These control device are almost always some kind of firewall. With the growing problem of network security, the most users are increasingly concerning about network security products. Firewall, which is not only the first network security products but also has the most users, has been favored by users and R&D institutions. The personal firewall used in PC has largely become the protector of individual users’ security.
    This article describes the development of personal firewall status, some technical characteristics of VC++6.0 and the MFC program, then gives a detailed introduction and description of a packet-filtering-based individual firewall’s development. A simple personal firewall development process can be clearly seen through this article. In the firewall, users can set their own filtering rules, in order to attain the filtering with different source IP, destination IP, source port, destination port and protocol.Program can be minimized into the system tray icon, protecting user in the background.It allows users to save the current rules into a file as *.rul.
    The firewall is composed of the following modules: adding filter rules module, display filter rules module, storage filter rules module, storage file module, installation and unloading rules module, IP packet driver module. Users can finish the operation by using main menu and button and protect the system effectively.
    Keywords:Personal Firewall, Packet Filter, Network Security, MFC
    1 绪论1.1 研究背景随着网络技术的飞速发展,网络安全问题日益突出。防火墙是目前广泛使用的一种网络安全技术,已成为企业内部与公用网络之间的一道必备的屏障,个人用户也纷纷安装了个人防火墙软件。防火墙往往放在网络的出口,成为一个信息流量的阻塞点,若造成网络阻塞,再安全的防火墙也无法应用。在实现中需要解决的主要问题是如何提高包过滤的性能。
    包过滤防火墙是最简单的一种防火墙,它在网络层截获网络数据包,根据防火墙的规则表,来检测攻击行为。包过滤防火墙一般作用在网络层(IP层),故也称网络层防火墙(Network Lev Firewall)或IP过滤器(IP filters)。数据包过滤(Packet Filtering)是指在网络层对数据包进行分析、选择。通过检查数据流中每一个数据包的源IP地址、目的IP地址、源端口号、目的端口号、协议类型等因素或它们的组合来确定是否允许该数据包通过。在网络层提供较低级别的安全防护和控制。
    包过滤防火墙工作在网络层,对数据包的源及目地 IP 具有识别和控制作用,对于传输层,也只能识别数据包是TCP还是UDP及所用的端口信息,如下图所示。现在的路由器、Switch Router以及某些操作系统已经具有用Packet Filter控制的能力。
    由于只对数据包的IP地址、TCP/UDP 协议和端口进行分析,包过滤防火墙的处理速度较快,并且易于配置。
    防火墙大致可以分为两大类:包过滤防火墙和代理防火墙。其中包过滤技术由于可以与现有的路由器集成,也可以用独立的包过滤软件实现,使用较灵活,应用比较广泛。
    国内外常见的防火墙软件有:

    GoldTach。这是一个体积小巧但功能强大的个人防火墙,集成了4个主要的功能:防火墙、进程控制、邮件保护和网页内容过滤。GoldTach可以在应用层、TDI层和NDIS层截取和捕捉数据,根据现有的规则进行分析,删除恶意的数据来保护网络安全。用户可以查看和控制进出网络的所有IP包,控制网络应用的各种操作:访问网站、充当服务器和收发电子邮件等,通过改变电子邮件附件的扩展名来保护邮件安全,过滤恶意或者无用的Http内容。
    Norton PersonalFirewall。该防火墙能够提供完整的网络安全,防止重要资料被窃,并有过滤网站的功能,还能够阻隔各种黑客可能的入侵方式,以防止私人信息被窃取和损坏。
    Outpost FirewallPro。这是一款短小精悍的网络防火墙软件,功能是同类PC软件中较强的,甚至包括了广告和图片过滤、内容过滤和DNS缓存等功能。它能够预防来自Cookies、广告、电子邮件病毒、后门、窃密软件、广告软件和其它Intemet威胁。该软件不需额外配置就可使用,适合普通用户使用。
    天网个人防火墙。该防火墙提供多种预先设置的安全级别,同时也支持用户自定义应用程序的安全规则与系统的安全策略,支持应用程序通信控制,同时具备自动识别功能。此外,它还提供特洛伊木马和入侵检测功能,可以通过厂商的安全数据库自动查找系统的漏洞。天网个人防火墙占用系统资源较少,操作简单。
    费尔防火墙。费尔防火墙1.0版是完全基于SPI技术的,是一款用于展示防火墙开发技术的开放原代码软件。费尔防火墙2.0除了使用SPI技术外,在核心层还使用了NDIS HOOK技术,因此功能上比1.0版本要强,是一款不错的防火墙软件。
    瑞星防火墙和金山网镖。这是国内著名的商业防火墙软件,功能比较强大,工作原理都是规则匹配技术。国内个人电脑上主要安装的是这两类防火墙。

    在技术日益成熟的今天,网络安全尤为重要,人们使用防火墙、入侵检测、数据保护、病毒防护和行为控制等多种安全保护措施,使自己的计算机不受攻击。防火墙作为数据传入本地的第一过滤层,其重要性不言而喻。
    1.2 研究意义目前市场上大多数的防火墙产品仅仅是网关型的,虽然功能相当强大,但大多基于下述的假设:内部网是安全可靠的,所有的威胁都来自网外。因此,这些防火墙产品防外不防内,难以实现对企业内部局域网内主机之间的安全通信,也不能很好地解决每一个拨号上网用户所在主机的安全问题,而大多数个人上网之时,并没有置身于得到防护的安全网络内部。因此个人防火墙就显得尤为重要,可以帮助用户抵御一切来自非本计算机的恶意数据包。
    个人上网用户多使用Windows操作系统,而Windows操作系统本身的安全性并不如人意。各种Windows漏洞不断被公布,对用户计算机的攻击也越来越多。一般都是利用操作系统设计的安全漏洞和通信协议的安全漏洞来实现攻击。如假冒IP包对通信双方进行欺骗;对主机大量发送IP数据包进行轰炸攻击,使之崩溃;以及蓝屏攻击等。因此,为了保护主机的安全通信,个人用户可以选择使用防火墙。服务于Windows系统基于包过滤的个人防火墙,可以为世界上使用最广泛的Windows操作系统用户主机提供一定的网络安全保护。
    1.3 课题内容本文主要研究个人安全防御系统中包过滤系统的设计与实现,通过对现有包过滤技术深入的研究与分析,发现其中的不足之处,并在设计实现的过程中对其进行改进和完善。

    全面深入的研究现有的包过滤技术,分析比较每一种包过滤技术的优缺点,结合个人安全防御系统的特点确定所要使用的技术。
    本次毕业设计应首先分析防火墙的相关功能,结合本次毕业设计的相关要求写出需求分析;其次,综合运用以前所学的相关知识,在设计中以需求分析为基础,写出系统开发计划、实现流程及相关问题的实现方法;同时,在开发设计与实现中,要保存好相关的设计文档。

    2 包过滤防火墙技术2.1 包过滤防火墙技术简介防火墙是专用网络系统,旨在防止未经授权的访问或从,防火墙是用于防止未经授权的Internet网络的互联网连接的用户访问私营,尤其是内部网。
    本文只处理数据包过滤器,包过滤字段的标题是基于对网络资源的众所周知的方法限制访问滤波要求的能力,按照指定的数据包分类过滤规则。这些规则可以看作是头字段的逻辑功能的数据包。分类数据包也出现在计算其他领域,如路由,策略路由,区分服务质量,然而,并非所有的都使用基础多包头中的字段。例如,一个简单的包转发路由器只需要根据数据包进行分类在一个领域(目的地的IP地址)来执行正确的路线。过滤的概念和分类是紧密联系在一起。
    防火墙是内部、外部两个网络之间的一个阻隔,通过允许和拒绝经过防火墙的数据流,防止不希望的、未授权的通信,并实现对进、出内部网络的服务和访问的审计和控制防火墙对网络用户提供访问控制服务和通信安全服务,对网络用户基本上是“透明”的,并且只有授权的管理员方可对防火墙进行管理。
    防火墙一般要解决的安全问题可分为被保护系统即内部网的安全问题和自身的安全问题。防火墙产品主要分为两类:包过滤和应用级防火墙。
    包过滤防火墙根据安全功能策略建立包过滤规则。过滤规则的主要要素有源IP地址、目的IP地址、协议号、源端口、目的端口、连接标志和另外一些IP选项,以及包到达或发出的接口。
    包过滤防火墙工作在网络层,对数据包的源及目地 IP 具有识别和控制作用,对于传输层,也只能识别数据包是TCP还是UDP及所用的端口信息。现在的路由器、Switch Router 以及某些操作系统已经具有用 Packet Filter 控制的能力。由于只对数据包的IP地址、 TCP/UDP 协议和端口进行分析,包过滤防火墙的处理速度较快,并且易于配置。
    包过滤防火墙是用一个软件查看所流经的数据包的包头,由此决定整个包的命运。它可能会决定丢弃(DROP)这个包,可能会接受(ACCEPT)这个包(让这个包通过),也可能执行其它更复杂的动作。
    2.2 防火墙包过滤技术的特点包过滤防火墙工作在网络层,对数据包的源及目地IP具有识别和控制作用,对于传输层,也能识别数据包是TCP还是UDP及所用的端口信息。
    由于只对数据包的IP地址、TCP/UDP协议和端口进行分析,包过滤防火墙的处理速度较快,并且易于配置。
    优点:

    对于一个小型的、不太复杂的站点,包过滤比较容易实现。
    因为过滤路由器工作在IP层和TCP层,所以处理包的速度比代理服务器快。
    过滤路由器为用户提供了一种透明的服务,用户不需要改变客户端的任何应用程序,也不需要用户学习任何新的东西。因为过滤路由器工作在IP层和TCP层,而IP层和TCP层与应用层的问题毫不相关。所以,过滤路由器有时也被称为“包过滤网关”或“透明网关”,之所被称为网关,是因为包过滤路由器和传统路由器不同,它涉及到了传输层。
    过滤路由器在价格上一般比代理服务器便宜。

    缺点:

    一些包过滤网关不支持有效的用户认证。
    规则表很快会变得很大而且复杂,规则很难测试。随着表的增大和复杂性的增加,规则结构出现漏洞的可能性也会增加。
    这种防火墙最大的缺陷是:依赖一个单一的部件来保护系统。如果这个部件出现了问题,会使得网络大门敞开,而用户其至可能还不知道。在一般情况下,如果外部用户被允许访问内部主机,则它就可以访问内部网上的任何主机。
    包过滤防火墙只能阻止一种类型的IP欺骗,即外部主机伪装内部主机的IP,对于外部主机伪装外部主机的IP欺骗却不可能阻止,而且它不能防止DNS欺骗。虽然,包过滤防火墙有如上所述的缺点,但是在管理良好的小规模网络上,它能够正常的发挥其作用。一般情况下,人们不单独使用包过滤网关,而是将它和其他设备(如堡垒主机等)联合使用。

    综上可见,包过滤防火墙技术面太过初级,就好比一位保安只能根据访客来自哪个省市来判断是否允许他(她)进入一样,难以履行保护内网安全的职责。
    2.3 包过滤防火墙工作原理包过滤防火墙工作在OSI网络参考模型的网络层和传输层,它根据数据包头源地址,目的地址、端口号和协议类型等标志确定是否允许通过。只有满足过滤条件的数据包才被转发到相应的目的地,其余数据包则被从数据流中丢弃。
    包过滤方式是一种通用、廉价和有效的安全手段。之所以通用,是因为它不是针对各个具体的网络服务采取特殊的处理方式,适用于所有网络服务;之所以廉价,是因为大多数路由器都提供数据包过滤功能,所以这类防火墙多数是由路由器集成的;之所以有效,是因为它能很大程度上满足了绝大多数企业安全要求。
    在整个防火墙技术的发展过程中,包过滤技术出现了两种不同版本,称为“第一代静态包过滤”和“第二代动态包过滤”。
    第一代:静态包过滤
    这种类型的防火墙根据定义好的过滤规则审查每个数据包,以便确定其是否与某一条包过滤规则匹配。过滤规则基于数据包的报头信息进行制订。报头信息中包括IP源地址、IP目标地址、传输协议TCP、UDP、ICMP等等、TCP/UDP目标端口、ICMP消息类型等。包过滤类型的防火墙要遵循的一条基本原则是“最小特权原则”,即明确允许那些管理员希望通过的数据包,禁止其他的数据包。
    第二代:动态包过滤
    这种类型的防火墙采用动态设置包过滤规则的方法,避免了静态包过滤所具有的问题。这种技术后来发展成为所谓包状态监测(Stateful Inspection)技术。采用这种技术的防火墙对通过其建立的每一个连接都进行跟踪,并且根据需要可动态地在过滤规则中增加或更新条目。
    包过滤方式的优点是不用改动客户机和主机上的应用程序,因为它工作在网络层和传输层,与应用层无关。但其弱点也是明显的:过滤判别的依据只是网络层和传输层的有限信息,因而各种安全要求不可能充分满足;在许多过滤器中,过滤规则的数目是有限制的,且随着规则数目的增加,性能会受到很大地影响;由于缺少上下文关联信息,不能有效地过滤如UDP、RPC一类的协议;另外,大多数过滤器中缺少审计和报警机制,它只能依据包头信息,而不能对用户身份进行验证,很容易受到“地址欺骗型”攻击。
    包过滤是一种内置于Linux内核路由功能之上的防火墙类型,其防火墙工作在网络层。
    使用过滤器。数据包过滤用在内部主机和外部主机之间,过滤系统是一台路由器或是一台主机。过滤系统根据过滤规则来决定是否让数据包通过。用于过滤数据包的路由器被称为过滤路由器。
    数据包过滤是通过对数据包的IP头和TCP头或UDP头的检查来实现的,主要信息有:

    IP源地址
    IP目标地址
    协议(TCP包、UDP包和ICMP包)
    TCP或UDP包的源端口
    TCP或UDP包的目标端口
    ICMP消息类型
    TCP包头中的ACK位
    数据包到达的端口
    数据包出去的端口

    在TCP/IP中,存在着一些标准的服务端口号,例如,HTTP的端口号为80。通过屏蔽特定的端口可以禁止特定的服务。包过滤系统可以阻塞内部主机和外部主机或另外一个网络之间的连接,例如,可以阻塞一些被视为是有敌意的或不可信的主机或网络连接到内部网络中。
    过滤器的实现。数据包过滤一般使用过滤路由器来实现,这种路由器与普通的路由器有所不同。
    普通的路由器只检查数据包的目标地址,并选择一个达到目的地址的最佳路径。它处理数据包是以目标地址为基础的,存在着两种可能性:若路由器可以找到一个路径到达目标地址则发送出去。
    过滤路由器会更加仔细地检查数据包,除了决定是否有到达目标地址的路径外,还要决定是否应该发送数据包。“应该与否”是由路由器的过滤策略决定并强行执行的。路由器的过滤策略主要有:

    拒绝来自某主机或某网段的所有连接。
    允许来自某主机或某网段的所有连接。
    拒绝来自某主机或某网段的指定端口的连接。
    允许来自某主机或某网段的指定端口的连接。
    拒绝本地主机或本地网络与其它主机或其它网络的所有连接。
    允许本地主机或本地网络与其它主机或其它网络的所有连接。
    拒绝本地主机或本地网络与其它主机或其它网络的指定端口的连接。
    允许本地主机或本地网络与其它主机或其它网络的指定端口的连接。

    2.4 数据包过滤技术这种技术是在网络中适当的位置对数据包实施有选择的通过,选择依据,即为系统内设置的过滤规则(通常称为访问控制表——AccessControl List),只有满足过滤规则的数据包才被转发至相应的网络接口,其余数据包则被从数据流中删除。
    包过滤在本地端接收数据包时,一般不保留上下文,只根据目前数据包的内容做决定。根据不同的防火墙的类型,包过滤可能在进入、输出时或这两个时刻都进行。可以拟定一个要接受的设备和服务的清单,一个不接受的设备和服务的清单,组成访问控制表。在主机或网络级容易用包过滤接受或决绝访问,例如,可以允许主机A和主机B之间的任何IP访问,或者拒绝除A外的任何设备对B的访问。
    包过滤的设置:

    必须知道什么是应该和不应该被允许的,即必须制定一个安全策略。
    必须正式规定允许的包类型、包字段的逻辑表达。
    必须用防火墙支持的语法重写表达式。

    2.5 数据包过滤类型2.5.1 IP包过滤IP分段字段用来确定数据包在传输过程中是否被重新分段,分段带来的问题是只有第一个段有高层协议的报头(如TCP头),而其他的段中没有。数据包过滤器一般是让非首段包通过,而仅对第一个分段进行过滤,因为目标主机如果得不到第一个分段,也就不能组装一个完整的数据包,因此这样做是可以接受的。强大的防火墙应该考虑非第一个分段有可能泄露有用的信息,比如出站的NFS数据包几乎肯定要分段,内部网中的敏感数据经过NFS传输可能会泄露,因此防火墙要根据第一个分段的操作策略来决定是否转发非第一个分段。
    IP分段也经常用来进行拒绝服务攻击。攻击者向目标主机发送第一个分段包,防火墙对这种包不作处理直接让其通过,目标主机得不到第一个分段来重组数据包时,会放弃该包,同时发一个ICMP“数据组装超时”的包给源主机。如果目标主机大量收到这种非第一个分段包,它需要占用大量的CPU时间来处理。当达到一定极限之后,目标主机就不能处理正常的服务了,而造成拒绝服务攻击。此外返回的ICMP也会泄露有用的消息,因此对这种ICMP,防火墙应该过滤掉。
    2.5.2 TCP包过滤TCP是面向联接的可靠传输协议,TCP的可靠主要是通过下面三条来保证的:目标主机将按发送的顺序接受应用数据; 目标主机将接受所有的应用数据; 目标主机将不重复接受任何数据。
    TCP协议通过对错误的数据重传来保证数据可靠到达,并且事先要建立起联接才能传输。如果要阻止TCP的联接,仅阻止第一个联接请求包就够了。因为没有第一个数据包,接受端不会吧之后的数据组装程数据包,且不会建立起联接。TCP的启动联接请求包中的ACK位为0,而其他的数据包ACK位为1,所以可以通过对ACK位的判断来确定是否是启动联接请求。
    2.5.3 UDP数据包过滤与TCP数据包结构相比, UDP数据包要比TCP数据包简单得多,这是因为UDP是一种无联接得协议,而TCP是一种有联接得协议。
    UDP不向TCP那样可靠,它得传输就像邮局发明信片一样,发出去后,得不到答复,不知道明信片是否真的到达了目的地。UDP数据包到通过MTU(最大传输单元)小的网络需要分段,然后各段分别传输,任何一个片段丢失后,数据包就损坏了,而UDP没有重传机制,这样就不能保证数据传输的完整性。即使数据包不分段,数据包也可能由于错误路由或网络拥挤而丢失。
    UDP的返回包的特点时目标端口是请求包的源端口,目标地址是请求包的源地址,源端口是请求包的目的端口,源地址是请求包的目标地址。因此,过程2的数据包被阻塞,而过程1的数据包被允许进入。
    2.5.4 源端口过滤在前面的例子中,过滤规则用到了源端口,如果防火墙在过滤数据包时不考虑源端口,很容易给入侵者可乘之机。假设路由器不支持检查源端口,要实现发送电子邮件的功能,规则如表2.1所示。
    规则A、B允许入站的SMTP联接;规则C、D允许出站的SMTP联接。



    规则
    方向
    源地址
    目标地址
    协议
    源端口
    目标端口
    动作




    A

    116.111.4.1
    任意
    TCP
    /
    25
    拒绝


    B

    116.111.4.1
    任意
    TCP
    /
    1023
    任意


    C

    116.111.4.1
    任意
    TCP
    /
    25
    允许


    D

    116.111.4.1
    任意
    TCP
    /
    1023
    允许



    2.5.5 ACK位在数据包过滤中的作用ACK位在数据包过滤中的作用是很关键的。假设防火墙不考虑ACK位,那么对于允许内部网络主机利用Telnet服务访问Internet的策略可以以下方式实现。
    如果有一个用户在他的主机上,用端口号23联接到内部网主机的一个大于1023的端口上,则这种联接将会被允许,可见,系统存在着安全缺口。
    一般只检查返回包的ACK位,因为联接请求包的ACK位可能不会被置位,而返回包ACK位一定会被置位。当加上ACK位检测后,得到如表2.2所示的规则。



    规则
    方向
    源地址
    目标地址
    协议
    源端口
    目标端口
    ACK设置
    动作




    A

    116.111.4.1
    任意
    TCP
    1023
    23
    任意
    允许


    B

    任意
    116.111.4.1
    TCP
    23
    1023

    允许



    当黑客试图通过端口23建立入站联接时,因为第一个请求包的ACK不被置位,所以该包回被禁止进入你的内部网络,第一个联接请求包被拒绝后,联接就很难建立起来了。
    如果入侵者把第一个数据包的ACK位置位,则该数据包可以通过防火墙,但目标主机会把这个数据包当作以前联接中的一个数据包,而不是建立一个新的联接。因为这个数据包不属于目标主机所知的任何联接(序列号不能匹配),所以它被抛弃掉。
    2.6 开发工具2.6.1 VC++ 6.0混合型面向对象程序设计语言既支持面向对象设计方法,也支持面向过程设计方法和结构化设计方法,最典型的是C++语言。
    C++作为一种应用最广泛的面向对象程序设计语言,具有类、对象、消息等概念,全面支持面向对象技术的抽象性、封装性、继承性和多态性特征。
    Visual C++6.0是微软公司推出的开发Win32应用程序的、面向对象的可视化集成工具。该工具最大优点就是提供了功能强大的MFC类库,MFC是一个很大的C++类层次结构,其中封装了大量的类及其函数,很多Windows程序所共有的标准内容可以由M-FC的类来提供,MFC类为这些内容提供了用户接口的标准实现方法,程序员所要做的就是通过预定义的接口把具体应用程序特有的东西填入这个轮廓,这将简化编程工作,大大地减少程序员编写的代码数量,使编程工作变得更加轻松容易。
    Visual C++6.0不仅是一个C++编译器,而且是一个基于Windows操作系统的可视化集成开发环境(integrateddevelopment environment,IDE)。Visual C++6.0由许多组件组成,包括编辑器、调试器以及程序向导AppWizard、类向导Class Wizard等开发工具。这些组件通过一个名为Developer Studio的组件集成为开发环境。Visual C++具有发展历史长、开发范围广泛、开发的应用程序运行效率高以及具备成熟的开发技术模式等特点。
    微软公司在Visual C++6.0中保留了传统的开发模式,同时扩展C++语言,让V-isual C++6.0在编写纯粹的应用程序的同时,依然可以利用现有的成熟技术进行非托管应用程序的开发。
    2.6.2 MFCMFC(MicrosoftFoundation Classes,微软基础类),同VCL类似,是一种Appl-ication Framework,随微软Visual C++ 开发工具发布。该类库提供一组通用的可重用类库供开发人员使用。大部分类均从CObject直接或间接派生,只有少部分类例外。
    MFC 应用程序的总体结构通常由开发人员从MFC类派生的几个类和一个CWinA-pp类对象(应用程序对象)组成。MFC提供了MFC AppWizard自动生成框架。此外MFC的部分类为MFC/ATL通用,可以在Win32 应用程序中单独包含并使用这些类。由于其易用性,初学者常误认为VC++开发必须使用MFC。这种想法是错误的。作为Application Framework, MFC的使用只能提高某些情况下的开发效率,只起到辅助作用,而不能替代整个Win32 程序设计。
    MFC实际上是微软提供的用于在C++环境下编写应用程序的一个框架和引擎,VC++是Win OS下开发人员使用的专业C++ SDK,MFC就是挂在这上面的一个辅助软件开发包。
    MFC是Win API与C++的结合,是一种软件编程的规范,但不是一种程序开发语言本身,可以允许用户使用各种各样的第三方编程语言来进行对Win OS下应用程序的开发,使这些被开发出来的应用程序能在Win OS下运行,比如VB、VC++、Java和Dehpi编程语言函数本质上全部源于API。
    MFC是一个很大的C++类层次结构,其中封装了大量的类、接口及函数,可以将诸如窗口类定义、注册及窗口创建等操作过程通过一定的处理机制自动完成。
    从物理角度看,MFC是一个类库,对应于Windows下的一系列MFC *.dll文件,MFC编程的本质就是选择该类库中合适的类来完成指定功能。
    从逻辑角度来看,MFC是一个应用程序框架,是一种新的程序开发模式。在该模式下,对程序的控制主要由MFC框架完成。
    因此程序员所要做的就是通过预定义的接口把具体应用程序特有的东西填入这个轮廓,这将简化编程工作,大大地减少程序员编写的代码数量,使编程工作变得更加轻松容易。
    3 防火墙系统构成3.1 需求分析该防火墙的主要功能是实现包过滤,其他功能主要包括以下几个方面。

    能设置过滤规则,包括:IP地址、子网掩码、端口号、协议。
    能添加删除规则。
    能将过滤规则保存。
    能对过滤规则进行安装和卸载操作。
    能正确完整的显示所添加的过滤规则。

    3.2 设计思路根据程序的需求来完成功能和模块化设计的思想,总体设计思路如下:

    任何程序都必须具有和用户进行信息交互的功能,因此用户接口部必须考虑,根据功能要求,该部分应具备:用户操作的功能菜单、能对过滤规则进行设置、显示规则界面、添加规则界面。
    这样程序的功能模块应该有:过滤规则添加删除功能模块,过滤规则显示功能模块,过滤规则存储功能模块,文件储存功能模块,安装卸载规则功能模块。

    3.3 功能模块构成
    3.4 功能模块介绍过滤规则添加删除功能模块
    包过滤防火墙要进行数据包过滤就需要按照用户定义的规则进行包过滤,该功能模块就是使用户能够添加或删除过滤规则。过滤规则主要包括:源IP地址、子网掩码、端口号,目的IP地址、子网掩码、端口号,协议,以及对符合该规则的数据包是放行还是阻止进行设置。然后将设置好的规则添加到存储功能模块。
    过滤规则显示功能模块
    该功能用于显示用户添加的规则,能够对每一条规则进行删除、安装、卸载的操作,使防火墙过滤规则能够很详细的显示给用户。
    过滤规则存储功能模块
    该功能用于存储用户添加的过滤规则,接受用户对每一条规则的操作,并按照用户的操作将规则进行处理。如:安装规则,则把用户选择的规则安装到IP过滤驱动,IP接收到此规则后按照此规则进行数据包过滤。
    文件存储功能模块
    使用户添加的过滤规则能够保存成文件的形式方便储存,在用户添加规则后可以选择某一条规则进行保存,防火墙会将该规则保存为后缀名为.rul的文件,在下次打开防火墙的时候可以直接加载该规则。
    文件载入功能模块
    相对于文件储存功能模块,该功能是实现用户可以导入一个后缀名为.rul的并且保存了有效规则的文件。
    安装卸载功能摸块
    防火墙要过滤数据包,就需要将IP过滤驱动按照定义的规则进行过滤。用户通过添加规则将规则存储于防火墙的存储功能模块中,想要将规则发送给IP过滤驱动,就需要对该规则进行安装。安装和卸载的功能就是将过滤规则传送给IP过滤驱动或是将已安装的规则从过滤驱动中删除。
    IP封包过滤驱动功能模块
    该功能模块是整个包过滤防火墙的核心部分,IP封包过滤驱动能按照用户定义的规则对数据包做出阻止或是放行的选择。
    4 系统实现4.1 程序关键类4.1.1 应用程序类CFireWallAPP每个MFC应用程序都必须包括一个从CWinApp派生的应用程序类,在本程序中的应用程序类就是CFireWAllApp。应用程序类构成了应用程序的主执行线程,它封装了一个Windows应用程序的初始化、运行和终止。
    4.1.2 主框架类CMainFrame主框架类CMainFrame构成整个程序的框架,包括菜单、工具、按钮等。它构成了程序功能的主框架。下面列出了CmainFrame类中的主要方法和变量。在主框架类CMainFrame中定义了应用程序的所有基本功能。
    class CMainFrame:public CFrameWnd{protected: BOOL Installed; //规则安装标志TRUE-已安装,FALSE-未安装protected: BOOL started; //开始过滤的标志,TRUE-已开始,FALSE-未开始 TDriver filterDriver; //定义一个TDriver类的变量, TDriver ipFltDrv; //protected: BOOL AddFilterToFw(); //AddFilterToFw完成将过滤钩子安装到防火墙的功能。 //{{AFX_MSG(CMainFrame) afx_msg void OnAppExit(); //退出程序 afx_msg void OnButtonadd(); //添加规则按钮 afx_msg void OnButtondel(); //删除规则按钮 afx_msg void OnButtonstart(); //开始过滤按钮 afx_msg void OnButtonstop(); //停止过滤按钮 afx_msg void OnButtonInstall(); //安装规则 afx_msg void OnButtonuninstall(); //卸载规则 afx_msg void OnMenuAddRule(); //添加规则菜单 afx_msg void OnMenuDelRule(); //删除规则菜单 afx_msg void OnMenuInstallRules(); //安装菜单 afx_msg void OnMenuUninstallRules();//卸载规则菜单 afx_msg void OnMenuStart(); //开始过滤菜单 afx_msg void OnMenuStop(); //停止过滤菜单 afx_msg void OnMenuSaveRules(); //保存规则菜单 afx_msg void OnMenuLoadRules(); //加载规则菜单 //}}AFX_MSG};
    4.1.3 文档类CFireWallDocMFC程序中的文档类是用来存储数据变量的。在本程序中CFireWallDoc主要用来存储用户添加的规则,当用户添加规则或删除规则时,就要向文档类CFireWallDoc中写入数据;当视图类CFireWallView需要将用户添加的规则显示在规则列表时,或者将规则安装到驱动,就需要从文档类CFireWallDoc中读取数据。
    其中RuleInfo rule[MAX_RULES]是_RuleInfo结构体的一个变量,该数组用来存储规则,_RuleInfo类详细情况见5.1.5节介绍。
    class CFireWallDoc:public CDocument{public: unsigned int nRules; //规则序数 RuleInfo rules[MAX_RULES]; //最大规则数 int AddRule();//添加规则 void DeleteRule(unsigned int position);//删除规则 void ResetRules(); //重置规则,即在加载规则前,需要删除规则列表中及存储在文档类CFireWallDoc中的所有规则};
    4.1.4 视图类CFireWallView视图类一般是用来显示信息的,在本程序中,CFireWallView主要用来在规则列表中显示存储在文档类CFireWallDoc中的规则。
    class CFireWallView:public CFormView{public: CFireWallDoc* GetDocument(); //指针指向文档类,和文档类CFireWallDoc关联。 //{{AFX_VIRTUAL(CFireWallView) public: protected: virtual void OnInitialUpdate(); //在这个函数中初始化规则列表 //}}AFX_VIRTUALpublic: void UpdateList(); //更新规则列表,和Doc文档类保持一致protected: void AddRuleToList(); //将文档类CFireWallDoc中的规则显示出来};
    4.1.5 _RuleInfo类_RuleInfo类是用来定义过滤规则的数据结构。
    typedef struct _RuleInfo{ unsigned long sourceIp; unsigned long sourceMask; unsigned short sourcePort; unsigned long destinationIp; unsigned long destinationMask; unsigned short destinationPort; unsigned int protocol; int action;}RuleInfo,*PRuleInfo;
    4.2 详细设计4.2.1 主界面程序主界面如图4.1所示。

    4.2.2 添加过滤规则添加过滤规则的功能是通过一个“添加规则”对话框完成,如图4.2所示。

    添加规则功能是将对话框中的规则添加到存储数据的文档中。分两个步骤:
    1.取得添加规则对话框中的数据
    int result; UpdateData(TRUE); //使控件列表与控件关联 result=inet_addr(m_ipsource,&srcIp); //从源IP地址编辑框获取源IP地址赋给srcIp result = inet_addr(m_srcMask, &srcMask);//从源IP掩码编辑框获取源IP地址掩码赋给srcMask。 result=inet_addr(m_ipdestination, &dstIp);//从目的IP地址编辑框获取目的IP地址赋给dstIp。 result = inet_addr(m_dstMask, &dstMask);//从目的IP掩码编辑框获取目的IP掩码赋给dstMask。 if(m_protocol == "TCP") protocol = 6; else if(m_protocol == "UDP") protocol = 17; else if(m_protocol == "ICMP") protocol = 1; else if(m_protocol == "所有") protocol = 0; if(m_action == "放行") cAction = 0; else cAction = 1; srcPort = m_portsource; //源端口 dstPort = m_portDestination; //目的端口
    2.将取得的数据添加到文档类中
    BOOL CFireWallDoc::AddRule(unsigned long srcIp, unsigned long srcMask, unsigned short srcPort, unsigned long dstIp, unsigned long dstMask, unsigned short dstPort, unsigned int protocol, int action){ rules[nRules].sourceIp = srcIp; rules[nRules].sourceMask = srcMask; rules[nRules].sourcePort = srcPort; rules[nRules].destinationIp = dstIp; rules[nRules].destinationMask = dstMask; rules[nRules].destinationPort = dstPort; rules[nRules].protocol = protocol; rules[nRules].action = action; nRules++; return TRUE;}
    实现添加规则功能的程序流程图如图4.3所示。

    4.2.3 删除过滤规则删除规则时,首先需要确定所要删除的规则,再将其从文档类中删除,同时更新视图类的显示。当正在进行过滤时,则要先停止过滤,才能删除规则。
    删除规则
    void CMainFrame::OnButtondel(){ CFireWallView *view = (CFireWallView *)GetActiveView(); CFireWallDoc *doc = (CFireWallDoc *)GetActiveDocument(); POSITION pos = view->m_rules.GetFirstSelectedItemPosition(); //选中的规则 if(started == TRUE) //如果正在过滤 {CString strTemp; strTemp.Format("请先停止过滤");} int position; position = view->m_rules.GetNextSelectedItem(pos); //position是当前选择的规则的下一条的序数 CFireWallDoc *doco = (CFireWallDoc *)GetActiveDocument(); //关联文档类 doco->DeleteRule(position); //调用DeleteRule()函数删除规则 view->UpdateList(); //更新规则列表的显示}
    实现删除规则功能的程序流程如图4.4。

    void CFireWallDoc::DeleteRule(unsigned int position){ if(position >= nRules) return; if(position != nRules - 1)//如果删除的规则不是最后一条,则将它删除后,后面的规则要往前移动 { unsigned int i; for(i = position + 1;i<nRules;i++) { rules[i - 1].sourceIp = rules[i].sourceIp; rules[i - 1].sourceMask = rules[i].sourceMask; rules[i - 1].sourcePort = rules[i].sourcePort; rules[i - 1].destinationIp = rules[i].destinationIp; rules[i - 1].destinationMask = rules[i].destinationMask; rules[i - 1].destinationPort = rules[i].destinationPort; rules[i - 1].protocol = rules[i].protocol; rules[i - 1].action = rules[i].action; } } nRules--;}
    DeleteRule()调用的流程图如图4.5所示。

    4.3 驱动程序设计4.3.1 简介基于Firewall-Hook Driver的包过滤驱动程序位于核心态,运行效率高,主要用于在IP过滤驱动中拦截所有的网络数据包,根据过滤规则判别是否接收或发送数据包。同时处理上层应用程序发送的IRP,接收应用程序发送的过滤规则等。
    安装过滤函数之前,先将过滤函数的地址填入IP_SET_FIREWALL_HOOK_INFO结构的FirewallPtr指针中,Add设置为TRUE,并指定该过滤函数优先级Priority,然后向IP设备发送IOCTL控制码IOCTL_IP_SET_FIREWALL_HOOK,这样就完成了过滤函数的安装。卸载过滤函数的时候只用把Add设置为FALSE就行了,其他参数和安装时一样。
    每个过滤函数可以设置一个优先级,系统调用这些函数的时候按照优先级的顺序进行,直到某个函数返回“丢弃包”为止。如果所有的过滤函数都返回“允许包”,那么这个包才能顺利通过系统。可以把这些过滤函数想象成一个过滤链,所有的函数按照优先级排列,如果一个函数返回“丢弃包”,这条过滤链就断开了。
    4.3.2 结构图驱动程序结构如图4.6所示。

    4.3.3 该驱动的优点在Windows中这不是开发防火墙的唯一方法,其它的有诸如 NDIS防火墙,TDI防火墙,Winsock分层防火墙,包过滤API等等。而Filter-Hook Driver的优点在于:

    这种方法所拥有的弹性可以使你过滤所有IP层(或以上)的通讯。但不能过滤更低层的头部数据,例如:不能过滤以太帧数据。需要用NDIS过滤器来做。这是一种简单的方法。安装防火墙和执行过滤功能非常简单。但包过滤API(Packet Filtering API)更加容易使用,尽管它缺少弹性,例如不能处理包的内容,不能用包过滤API修改内容。
    4.3.4 本程序的驱动设计本程序驱动的设计核心是通过使用TDriver类向DrvFltIp驱动程序发送控制代码(START_IP_HOOK, STOP_IP_HOOK, ADD_FILTER, CLEAR_FILTER),达到实现数据包过滤的目的。
    1.程序初始化时,调用LoadDriver()加载DrvFltIp驱动
    CMainFrame::OnCreate(){ ipFltDrv.LoadDriver("IpFilterDriver","System32\\Drivers\\IpFltDrv.sys",NULL,TRUE);}
    2.当用户单击“开始过滤”按钮时,程序向驱动发送START_IP_HOOK控制代码,开始过滤
    CMainFrame::OnButtonstart(){ filterDriver.WriteIo(START_IP_HOOK,NULL,0);}
    3.当用户单击“停止过滤”按钮时,程序向驱动发送START_IP_HOOK控制代码,停止过滤
    CMainFrame::OnButtonstop(){ filterDriver.WriteIo(STOP_IP_HOOK,NULL,0);}
    4.当用户单击“安装规则”按钮时,程序向驱动发送ADD_FILTER控制代码
    CMainFrame::OnButtonInstall(){ AddFilterToFw();}AddFilterToFw(){ filterDriver.WriteIo(ADD_FILTER, &pf, sizeof(pf));}
    5.当用户单击“卸载规则”按钮时,程序向驱动发送CLEAR_FILTER控制代码
    CMainFrame::OnButtonuninstall(){ filterDriver.WriteIo(CLEAR_FILTER, NULL, 0);}
    5 程序结果测试计算机位于网关地址为10.0.0.2的局域网内,本地IP地址为:10.0.0.15。通过局域网连接于外部网络,可以PING通本地网关地址10.0.0.2和电信DNS服务器地址61.139.2.69,如图5.1和图5.2所示。


    运行防火墙,点击“添加”按钮进行过滤规则设置,如图5.3所示。源地址:10.0.0.2 目的地址:10.0.0.15端口号:0(所有端口)协议:由于PING命令基于ICMP协议,所以协议选择:ICMP行为:丢弃


    点击“添加”按钮将规则保存到防火墙:如图5.4。


    点击“安装”防火墙将过滤规则添加到过滤驱动,点击“开始”防火墙开始按照规则进行数据包过滤,如图5.5所示。

    由图5.5可以看出原来本地计算机可以和本地网关(路由器)进行ICMP数据包收发,也能和电信DNS服务器进行数据包收发。而当防火墙设置为过滤源地址为10.0.0.2、协议为ICMP的规则之后运行,本地计算机将不能和本地网关(路由器)进行数据包收发,PING命令显示为“Request timed out”。但是本地计算机还能和电信DNS服务器61.139.2.69进行数据收发。
    6 总结防火墙是建立在本地主机与外部网络的一道屏障,可以根据用户需求来改变其自身既定过滤规则,以满足用户的实际需求。
    本防火墙实现了基本的包过滤功能。如设定本机IP为目的地址,协议类型为ICMP,那么别人就不能ping通本机。又如TCP协议的21端口关闭,别人就不能和该主机使用FTP传输。
    本防火墙还实现了用户手动选择导入导出防火墙规则、对当前规则的删除或修改、添加一条新的规则等功能。
    本程序提供了基本的包过滤功能,界面简单易用,代码易读,更有保存规则读取规则使用户每次使用不必重新输入规则,加入注册表启动项使之能随系统启动而启动,就能从用户开机为用户提供保护。
    可以提高的地方有:现在需要用户手动输入源或者目标IP地址、端口以及协议,这对于一些不太了解计算机网络的用户来说使用起来就相对要困难些了;保存规则时程序不懂得把后缀名自动添加上去,使得如果不保存为*.rul文件,下次读取时候可能不一定能注意到该文件是规则文件。
    未来的防火墙必定继续向多元化功能和良好的性能及效率发展。随着硬件和网络的发展,个人防火墙的作用和地位越发提高,未来的防火墙将与入侵检测、病毒防护、数据保护以及程序行为控制等相结合,来保证本地主机全方位不受外部的攻击。入侵检测是对防火墙有益的补充,入侵检测系统能在入侵攻击对系统发生危害前,检测到入侵,并利用报警以及相关的数据保护和行为控制来驱逐该入侵,减少入侵攻击所造成的损失。同时使用日志审计功能,记录本次入侵特点,使防御系统变得更为智能化,从而可以避免系统再次受到相同的入侵。
    参考文献[1] 罗斌.Visual C++编程技巧精选集[M].北京:中国水利水电出版社,2008.9.573-605
    [2] 朱雁辉.Windows防火墙与网络封包截获技术[M].北京:电子工业出版社,2002.8.140-149
    [3] 邓全良.Winsock网络程序设计[M].北京:中国铁道出版社,2002.6.1-18
    [4] 唐克.MFC程序设计——Using VisualC++6.0[M]. 北京:北京希望电子出版社,2002.6.229-231
    [5] 文东,华进.Visual C++程序设计基础与项目实训[M].北京:中国人民大学出版社,2009.12.76-80
    [6] 唐彬,刘超.VisualC++案例开发集锦[M].北京:电子工业出版社,2005.6.123-125
    [7] 曾宪权.VisualC++.NET程序设计使用教程[M].北京:清华大学出版社,2007.7.65-71
    [8] 于永彦,王志坚,娄渊胜等.Visual C++程序设计实用案例教程[M].北京:北京大学出版社,2010.2.250-255
    [9] 叶树华.网络编程实用教程[M].北京:人民邮电出版社,2010.1.65-73
    [10] 方娇莉,李向阳.C语言程序设计[M].北京:中国铁道出版社,2010.1.114-122
    [11] 刘远生,辛一.计算机网络安全[M].北京:清华大学出版社,2009.4.178-195
    [12] 石磊,赵慧然.网络安全与管理[M].北京:清华大学出版社,2009.7.89-102
    [13] 骆耀祖.网络安全技术[M].北京:北京大学出版社,2009.6.186-206
    [14] Ido Dubrawksy,Chris Crayton,Michael Cross等.贾军保译.网络安全保护[M].北京:科学出版社,2009.10.208-214
    [15] Raven Alder,Josh Burke,Chad Keefer等.傅建明,潘宣辰,潘谧译.开放资源安全工具实践[M].北京:科学出版社,2009.10.36-41
    [16] Andreas.Hooking into NDIS and TDI[OL].http://www.rootkit.com/newsread.php?newsid=219
    [17] Mohamed G.Gouda,Alex X.Liu.Structured firewall design[J].Computer Networks.2006.6
    [18] Bruce Eckel.Thinking in C++(2nd Edition)[M].北京:机械工业出版社,2002.3
    致 谢感谢本次毕业设计的指导老师,从项目启动开始,一直孜孜不倦地给与我们整个小组成员悉心指导和耐心帮助,为我们解决开发中遇到的困难提供了最大的支持,使得我们能认真投入到开发工作中去。
    感谢开题答辩时的三位老师提出的细化要求,使整个毕业设计的方向更为明朗,也让我实现本课题少走了很多弯路。
    感谢毕业设计小组里其他同学给与的帮助,在这里,祝你们事业有成,身体健康!
    最后,再次向所有关心帮助过我的老师和同学表示诚挚的谢意!
    7  留言 2018-10-02 20:58:17

发送私信

世間萬物不及你眼中點點星辰

19
文章数
18
评论数
eject