《基于中间件的图书管理系统unix课程设计.doc》由会员分享,可在线阅读,更多相关《基于中间件的图书管理系统unix课程设计.doc(60页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、UNIX系统与软件开发课程设计说明书设计题目: 图书管理系统 专 业: 计算机科学与技术 指导教师: 班 级: 学 号: 姓 名: 同 组 人: 计算机科学与工程学院2014 年 6 月18 日前言在信息技术发展迅猛的二十一世纪的今天,我们需要掌握的不仅仅是科学文化知识,还需要把所学到的知识合理的运用到现实生活中来。科学技术是第一生产力,它给我们带来的不仅仅是生活中的各种便利和生活水平的不断提高,同时也给带给了我们各种各样的不同类型和不同层次的科技的领先发展的成果。在中间件诞生之前,多采用传统C/S二层结构。这种二层结构是计算机及软件技术发展的一大进步。一般而言,服务器是一个进程,它等待客户机
2、与其联系,提出某种类型的服务要求。C/S模式在操作过程中采取的是主动请求方式。服务对客户机服务可将结果或信息返回给客户机(双向),也可不返回(单向)。虽然它带来了相当的灵活性,但也逐渐暴露出其客户端和服务器端负担过重的现象,并且拓展性也较差,无法跨越不同的业务部门和业务系统。这不仅表现在技术上有难度,更重要的是在制度和安全方面。于是,三层结构出现了所谓三层结构,就是在原有的两层结构之间,增加一个中间层。该中间层既包括服务也包括请求中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源。中间件位于客户机/ 服务器的操作系统之上,管理计算资源和网络通讯。是连接两个
3、独立应用程序或独立系统的软件。相连接的系统,即使它们具有不同的接口,但通过中间件相互之间仍能交换信息。执行中间件的一个关键途径是信息传递。通过中间件,应用程序可以工作于多平台或 OS 环境。它的工作机制是:当客户端上的应用程序需要从网络中某个节点处获取一定的数据或服务时,这些数据和服务可能处于一个运行着和客户端不同的硬、软件、网络或操作系统的平台上。C/S应用程序中负责寻找数据的部分只需访问一个中间件系统,由中间件完成到网络中找到数据源或服务,进而实现传输客户请求、重组答复信息,最后将结果送回应用程序的任务。 本次设计的中间件是交易型中间件。交易型中间件是指用在不同行业、不同部门间的通讯转发和
4、协议转换的软件,在不同的行业、不同的系统间提供通讯转发和协议转换的桥梁作用。本次设计不是基于WEB的,不需要很多与WEB开发相关的知识,主要是利用UNIX系统提供的Socket库在网络底层,开发交易型中间件。本次设计的目的是掌握利用软件工程的思想方法和TCP/IP设计出用于不同行业和部门间的通讯转发或协议转换软件中间件,尤其掌握这种设计的思想和方法。目录一、系统环境11、硬件环境12、软件环境1二、设计目的及要求22.1设计目的22.2设计要求2三、总体设计43.1程序设计组成框图43.2程序设计类图53.3程序设计流程图6四、详细设计74.1基本套接字系统调用74.2 MySQL数据库在Un
5、ix的使用84.2.1 软件包需要84.2.2 MySQL服务配置94.2.3 MySQL客户端命令行工具94.2.4 客户端命令行94.2.5 MySQL开发接口9五、调试与测试115.1调试方法115.2测试结果分析及讨论11六、设计中遇到的问题及解决方法22七、源程序清单237.1数据库代码237.2服务器代码247.3中间件程序337.4客户端程序36八、心得体会57九、参考文献58一、系统环境1、硬件环境Pentium(R), 4 cpu 3.06GHz,512MB内存。2、软件环境该图书管理系统是在windows XP操作系统下使用Linux虚拟机环境,使用GNU C,在UNIX/
6、Linux make开发工具的管理和控制下,利用UNIX/Linux Socket库和MySQL数据库在网络的底层进行开发设计的。二、设计目的及要求2.1设计目的基于UNIX Socket和MySQL数据库,设计一个交易型中间件系统。这里的中间件是指交易型中间件。交易型中间件是指用在不同行业、不同部门间的通讯转发和协议转换的软件,在不同的行业、不同的系统间提供通讯转发和协议转换的桥梁作用。例如电子商务、银行代理业务软件等都是这种类型的软件。本设计不是基于WEB的,不需要很多与WEB开发相关的知识,主要是利用UNIX系统提供的Socket库在网络底层,开发交易型中间件。本设计的目的是使参与设计者
7、掌握利用软件工程的思想方法和TCP/IP设计出用于不同行业和部门间的通讯转发或协议转换软件中间件,尤其掌握这种设计的思想和方法。在很多场合中间件部分是必须的,因为在不同的行业的网络是不允许直通的。这里有政策的因素,有制度的要求,也有技术的成份。2.2设计要求(1)客户端客户端程序可命名为client,要求带有两个命令行参数一个是服务(自己定义,并保存在/etc/services中,比如mysvr1 5678),另一个是目的主机(自己定义,并保存在/etc/hosts内,也可使用DNS来解析),缺省时为本机。客户端至少要实现如下功能:用户管理;查询;交易(交费,购物等);撤销;留迹;本地业务统计
8、。客户端的环境可以是Windows系统,也可以的Linux系统。(2)中间件中间件程序命名为middle,要带有三个参数,一个是用于服务器的服务(名字,与客户端同),第二个作为请求的服务(自己定义,并保存在/etc/services中,要区别于客户端,比如mysvr2 5679),第三个为目的主机(定义在/etc/hosts内),缺省时为本机。中间件要完成与客户要求相符的功能:是本地的本地处理,否则发往服务器方。具体地是:接收客户方数据;组织服务器方所需数据;重组服务方返回数据,并返回给客户方;留迹;本地业务统计。中间件的环境可以是Windows系统,也可以的Linux系统。(3)服务器服务器
9、程序命名为server,要求带有一个服务参数,与中间件的mysvr2同服务器方程序要完成客户端或中间件提出的业务请求,并做好留迹工作。服务端环境必须是Linux系统。(4)留迹或log留迹或log工作在客户端、中间件和服务器三方都要做,以供统计或核对使用。客户端或中间件方可以使用文本文件或数据库,但在服务器方必须使MySql数据库。三、总体设计3.1程序设计组成框图设计过程中借助了中间件来实现主机和客户机之间的链接,它的工作机制是:当客户端上的应用程序需要从网络中某个节点处获取一定的数据或服务时,这些数据和服务可能处于一个运行着和客户端不同的硬、软件、网络或操作系统的平台上。C/S应用程序中负
10、责寻找数据的部分只需访问一个中间件系统,由中间件完成到网络中找到数据源或服务,进而实现传输客户请求、重组答复信息,最后将结果送回应用程序的任务。Server_mserver_1MiddleClient_2Client_1图3.1.1 中间件服务框图serverClient_nClient_1 图3.1.2 c/s客户/服务器模式框图3.2程序设计类图socket()建立服务方套接字描述符为sSocket()建立服务方套接字,描述符为sConnect()建立服务方连接Send()和write()向服务方发送请求客户方等待服务方Recv()和read()读取服务方数据Close()关闭最初套接字s
11、,结束服务器服务Close()关闭套接字ns,结束本次对话进行服务处理成功后返回与s具有相同特性的套接字accept(s)等待客户方链接Listen(s)通知TCP,准备接受bind(s)绑定套接字与本地地址和端口recv()和read()通过ns读取客户方数据Send()和writer()向客户方提供服务结果Close()关闭套接字s,结束本次通话图3.2.1 程序设计类图3.3程序设计流程图 开始登录结束查询用户管理员 输入密码续借删除添加借书还书显示借阅信息 请求服务中间件数据库服务器 和数据库交换数据图3.3.1 程序设计流程图四、详细设计4.1基本套接字系统调用 【1】创建套接字so
12、cket() 应用程序在使用套接字前,必须拥有一个套接字,系统调用socket()向应用程序提供创建套接字的手段。其调用格式如下:#includeint socket(int domain, int type, int protocol);该调用要接收3个参数,根据这3个参数建立一个套接字,并将相应的资源分配给它,同时返回一个整型套接字号,只和一个特定的协议相联系。实际上指定了相关五元组中的“协议”这一元。domain(协议族):AF_INET,AF_UNIX,AF_IPXtype(类型):SOCK_STREAM,SOCK_DGRAMprotocol(协议):0-让系统使用指定类型和协议族上的
13、默认协议。【2】绑定本地地址bind()当一个套接字用socket()创建后,存在一个名字空间(地址族),但它没有被命名,bind()将套接字地址(包括本地主机地址和本地端口地址)与所创建的套接字号绑定起来,即将名字赋予套接字,以指定本地半相关。其调用格式如下:#include int bind(int sockfd,const struct sockaddr *my_addr, int addrlen);说明:sockfd:为socket成功时的返回值套接字描述符。my_addr为本方地址数据结构。addrlen=sizeof(my_addr).【3】监听连接listen() 此调用用于面向
14、连接服务器,表明它愿意接收连接。1isten()需在accept()之前调用,其调用格式如下:#includeint listen(int s,int backlog);listen()在执行调用过程中可为没有调用过bind()的套接字s完成所必需的连接,并建立长度为backlog的请求连接队列。backlog定义最大长度的socket等待队列。默认值为5. 【4】connect(),accept()这两个系统调用用于完成一个完整相关的建立,其中connect()用于客户建立连接。accept()用于使服务器等待来自某客户进程的实际连接。connect功能:客户方调用发出的请求用法:int c
15、onnect(int sockfd,const structct sockaddr * server_addr, socklen_t addrlen); 在面向连接的协议中,该调用导致本地系统和外部系统之间连接实际建立。 accept服务器调用,从等待从编号为s的套接字上接受客户连接请求用法:int accept(int s, struct sockaddr *addr, socklen_t addrlen); connect与accept的说明调用accept()后,服务器等待从编号为s的套接字上接受客户连接请求,连接请求是由客户方的connect()调用发出的。当有连接请求到达时,acce
16、pt()调用将请求连接队列上的第一个客户方套接字地址及长度放入addr和addrlen,并创建一个与s有相同特性的新套接字号。新的套接字可用于处理服务器并发请求。 【5】数据传输:send()/write与recv()/read() 当一个连接建立以后,就可以传输数据了。常用的系统调用有send()和recv()。send()调用用于在参数s指定的已连接的数据报或流套接字上发送输出数据,格式如下:int send(int s,void *buf,int len,int flags);int recv(int s,void *buf,int len,int flags); recv/send可由
17、文件系统调用read/write所取代。在处理二进制数据处理时,后者优于前者。【6】关闭套接字:close()close()关闭套接字s,并释放分配给该套接字的资源;如果s涉及一个打开的TCP连接,则该连接被释放。close()的调用格式如下:int close(int s);4.2 MySQL数据库在Unix的使用4.2.1 软件包需要1)MySql服务器mysql-server-3.23.54a-11mysql-server-3.23.58-1.92)MySql客户端mysql-3.23.54a-11mysql-3.23.58-1.93)MySql开发接口库mysql-devel-3.23
18、.54a-11mysql-devel-3.23.58-1.94.2.2 MySQL服务配置 mysqyld服务要运行起来。最好是设为开机自动启动。方法: chkconfig level 2345 mysqld on ntsysv service mysqld start / stop /restart 图形方式4.2.3 MySQL客户端命令行工具MySqyl客户端命令行工具为mysql。其常用法为:mysql OPTIONS database output.tab常用参数有:-?, -help: 帮助-D, -database=DB_name:指定数据库-h, -host=Host_name
19、:指定主机-u, -user=DB_user_name:指定用户-p, -password=:指定密码4.2.4 客户端命令行 命令行提示符下输入:mysql 或 mysql u root进入mysql系统。提示符为“”,可以使用的命令有:show databases / tables;use database;create database db;create table tbl;drop database db/ table tbl;select from tbl where insert into tbl values update tbl set where delete from t
20、bl where 4.2.5 MySQL开发接口不同版本的MySql有不同的目录设置。头文件:目录:/usr/include/mysql使用:#include 说明:必要时可使用-I参数库文件:静态库:/usr/lib/mysql/libmysqlclient.a动态库:/usr/lib/mysql/libmysqlclient.so使用参数:-L/usr/lib/mysql -lmysqlclient初始化数据结构mysql_init(&mysql);连接数据库mysql_real_connect(&mysql,localhost,root,0,“mydb,0,NULL,0);执行查询语句m
21、ysql_querymysql_query(&mysql,SELECT * FROM person);/保存结果result=mysql_store_result(&mysql);处理结果集while(row=mysql_fetch_row(result)fprintf(stdout,%s|t%sn,row0,row2);mysql_free_result(result); /清理数据 mysql_close(&mysql); /关闭连接编译和链接方法编译链接时要使用-L和-l参数例如:cc -o mysql mysql.c -L/usr/lib/mysql -lmysqlclient五、调试
22、与测试5.1调试方法1) 安装组件:rpm ivh mysql-devel*.rpm2) 增加服务:vi /etc/services S1 1245/tcp S2 1246/tcp3) 连接数据库:mysql u rootmysql.script4) 运行服务器:cc -o server server.c -L/usr/lib/mysql -lmysqlclient ./server s15) 运行中间件:cc o middle middle.c ./middle s2 s1 localhost6) 运行客户端:cc o client client.c ./client s2 localhos
23、t5.2测试结果分析及讨论1)MySQL数据库的相关截图编写mysql.script脚本文件,在文件中编写创建数据库library,在该数据库下创建admi、books、borrow、test表,并插入相应的数据,具体内容如下图所示。 数据库library,如图5.2.1所示:图 5.2.1 数据库library中的相关表,如图5.2.2所示:图 5.2.2 数据库library中部分表的内容,如图5.2.3所示:图 5.2.32)开始时运行服务器程序server.c如图5.2.4所示:图5.2.4服务器通信过程中如图5.2.5所示:图 5.2.53)运行中间件程序middle.c,如图5.2
24、.6所示:图 5.2.64)运行客户端程序client.c,如图5.2.7所示:图 5.2.75)实现查询图书功能,如图5.2.8所示:图5.2.86)实现用户登录功能,且实现了密码不回显功能,如5.2.9所示:图 5.2.97)实现用户查询图书功能,如图5.2.10所示: 图 5.2.108)实现用户借书功能,如图5.2.11所示:图5.2.119)实现用户还书功能,如图5.2.12所示:图 5.2.1210)实现用户续借功能,如图5.2.13所示:图 5.2.1311)实现用户注销,如图5.2.14所示:图5.2.1412)实现管理员登录,且实现了密码不回显功能功能,如图5.2.15所示:
25、图 5.2.1513)实现管理员查询图书功能,如图5.2.16所示:图 5.2.1614)实现管理员增加图书功能,如图5.2.17所示:图 5.2.1715)实现管理员删除图书功能,如图5.2.18所示:图 5.2.18删除图书book10后再查询改图书,提示“未找到该图书”,说明确实删除成功,如图5.2.19所示:图5.2.1916)实现管理员注销功能,如图5.2.20所示:图 5.2.2017)退出系统,如图5.2.21所示:图5.2.21六、设计中遇到的问题及解决方法这是我们第一次学习关于中间件的知识,对它的具体运行只是有一定程度的了解,不是很深刻,在设计中由于对UNIX知识的掌握不好,
26、导致初期进度是相当的慢,在开始的几天里差不多就没有什么进度,后来通过我们小组成员的讨论、不断查阅资料及向老师请教,我们开始有了一点点的设计思路,设计过程中用到的知识不单单是课本上有的,还有的是课本上没介绍过的,因此这就需要我们多方的查阅资料和向老师请教。平时我们都习惯了使用Windows的编辑器,开始的时候由于UNIX的文档编辑和Windows有着很大的区别,UNIX是全字符编辑器,所以在初期使用UNIX进行的编辑的时候有点不知道该从那下手,后来经过学习知道在其编辑过程中我们可以使用终端通过命令来实现。还有在数据库的建立中,由于其基本程序中不带有数据库,一次我们必须自己建立一个数据库来存储信息
27、,但是我们不知道怎样在客户端和主机程序中插入数据库,以此来存储图书信息,在指导老师和同学的帮助下,还有借助网络查了一些资料后终于解决了这一问题,等等。在编写好程序后,发现在管理员增加图书模块,只能连续的增加图书,不能退出该选项。在仔细研究代码后,我在管理员增加图书的代码后添加了break语句,成功的解决了错误。其次原先若输入比菜单中选项大的数字,系统没有识别错误,继续执行。为了解决这个错误,我在客户端的主菜单部分添加了if-else语句,对字符进行判断和错误处理,成功的解决了该错误。其实设计中遇到的问题远比这多很多,因为掌握知识的程度不同,各种各样的编程问题都会遇到,我们坚持不懈,通过不断的学
28、习和查阅资料、向老师请教,最后通过努力完成了任务。七、源程序清单7.1数据库代码编写脚本文件mysql.script,并在脚本中编写如下内容:create database library;use library;create table books(id char(10) not null primary key,name char(50) not null,writer char(50),storage char(10);create table reader(id char(10) not null primary key,name char(50) not null,password
29、char(15),enable char(2) default 1);create table admi(id char(10) not null primary key,name char(50) not null,password char(15);create table borrow(r_id char(10) not null,b_id char(10) not null,b_date date,status char(2),primary key(b_id,r_id),foreign key(b_id) references books(id) on delete cascade
30、on update cascade,foreign key(r_id) references reader(id) on delete cascade on update cascade);insert into books values (1,book1,a,5);insert into books values (2,book2,b,6);insert into books values (3,book3,c,6);insert into books values (4,book4,d,10);insert into books values (5,book5,e,9);insert in
31、to books values (6,book6,f,4);insert into books values (7,book7,g,7);insert into reader values (00000,youke,123,1);insert into admi values (11111,root,123);7.2服务器代码#include #include #include #include #include #include #include #include#include#define rec_length 20getm(char buf,char result1050) /chan
32、ge format char *ip=NULL,*op=NULL,*temp=NULL,*p=NULL,*tmp=NULL; int i=0,j=0,n=0; temp=(char *)malloc(strlen(buf); strcpy(temp,buf); p=temp; strtok_r(temp,;,&op); while(tmp=strtok_r(NULL,;,&op)!=NULL) p=tmp; while(tmp=strtok_r(p,&ip)!=NULL) strcpy(resultij,tmp); p=NULL; j+; i+; j=0; free(temp);int opd
33、b(char *cmd,char *p,int flag) /operate database MYSQL mysql; MYSQL_RES *result; MYSQL_ROW row; int i,j,n=0; char buf256; if(mysql_init(&mysql)=NULL) printf(db init error!n); return -1; printf(Init db successfully!n); if(!mysql_real_connect(&mysql,localhost,root,0,library,0,NULL,0) printf(Connect err
34、or!n); mysql_close(&mysql); return -1; printf(Connect db successfully!n); printf(cmd=%sn,cmd); if(mysql_query(&mysql,cmd)!=0) printf(query database wrong!n); mysql_close(&mysql); return -1; if(flag=1) printf(bbbbbbbbbbbbbn); if(result=mysql_store_result(&mysql)=NULL) mysql_free_result(result); mysql
35、_close(&mysql); return -1; n=mysql_num_rows(result); i=0; j=0; if(p!=NULL) bzero(buf,sizeof(buf); while(row=mysql_fetch_row(result) strcat(buf,;); strcat(buf,row0); for(i=1;i30&r_id=%s,id); sprintf(cmd2,select * from borrow where r_id=%s,id); if(opdb(cmd1,NULL,1)=0)&(opdb(cmd2,NULL,1)s_port; if(bind(s,(struct sockaddr *)&sin,sizeof(sin)=-1) fprintf(stderr,Error: bind); close(s); exit(-6); if(listen(s,5)=-1) fprintf(stderr,Error: listen); close(s); exit(-6); while(1) fprintf(stderr,nttt Now wait connect .n); if(ns=accept(s,0,0)=-1)