我经常听一些人大谈把两层CS结构的应用转为三层CS结_第1页
我经常听一些人大谈把两层CS结构的应用转为三层CS结_第2页
我经常听一些人大谈把两层CS结构的应用转为三层CS结_第3页
我经常听一些人大谈把两层CS结构的应用转为三层CS结_第4页
我经常听一些人大谈把两层CS结构的应用转为三层CS结_第5页
已阅读5页,还剩96页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第二章 编程我经常听一些人大谈把两层C/S结构的应用转为三层C/S结构的应用,无论说的,还是听的,都兴高采烈,频频点头:好,好!转吧。不过,具体怎么“转”呢?是不是把两层C/S结构的程序放到什么容器里“煮”一下,再取出来就可以“吃”了?当然不行,看来一个“转”字还颇有点儿学问。如果您原来靠游泳过河,那我教您一种划船过河的方法,这条船就是中间件CICS当然您不能靠划船的经验来驱动它,CICS需要的是编程。学划船很简单,学CICS编程也一样简单,读了本章的内容就会知道。如果读者想用COBOL或JAVA来开发CICS的服务程序,请参阅CICS的其它技术资料,这里只提供了C语言的例子。不过,这里提供了

2、几乎所有常用的前端开发工具作为CICS客户的例子,也许这正是您所需要的,那么,请认真阅读后面的内容。如果您已经有足够多的预备知识,可以先阅读下一章,在建好一个实验环境后,再回到本章。2.1 建立一个简单的CICS应用CICS程序:GETTIME我们将要看到的这个CICS程序基本没有用到CICS强大的事务处理监控能力,所以更象是一个两层C/S的应用。但是因为它如此简单,我还是把它做为您学习CICS的入门程序。做过UNIX或NT的服务程序(UNIX经常叫DAEMON程序)朋友,会发现CICS服务程序非常容易实现,因为您不必去处理Socket、Named Pipe或FIFO之类的东西。是的,如果不考

3、虑价格因素,用CICS去实现许多一般的服务程序可是个省事的好办法。设想某公司要投资开发一个叫GETTIME的服务程序,其功能是公布服务器的时间,供他们的各种前端客户程序使用。这些程序必须能运行于各种常用的UNIX平台和WINDOWS NT,甚至可以移植到AS400和IBM大型机上。正在公司的编程高手们纷纷摩拳擦掌,准备大干一场时,一个初级的CICS程序员突然宣布他已在5分钟内完成了任务,并将得到一笔可观的报酬有这种好事吗?那我们不妨就来看看GETTIME的CICS解决方案。这是C语言作的CICS服务程序的清单(注意,这个源程序可以不加修改的运行在支持CICS的各种操作系统平台上):#inclu

4、de <time.h>#include "easycics.h"void main()struct tm *newtime;time_t aclock;if( InitEasyCics() ) ExitEasyCics();/* A */BeginWrite();/* B */time( &aclock );newtime= localtime( &aclock );SetValue( "TIME", asctime(newtime) ); /* C */ExitEasyCics();/* D */清单 2-1-1 (gett

5、ime.ccs)客户程序更加简单,下面是一些例子:1、ANSI C的客户程序见清单2-1-2:#include "ec.h"void main()char s200;ConnectServer( "CICSNT01", "TEST", "TEST" );/* A */CallProgramAndCommit("GETTIME");/* B */GetValue( "TIME", s );/* C */puts(s);清单 2-1-2以下是运行结果:D:cics>gett

6、imeThu Jan 27 17:35:14 2000清单 2-1-32、使用OLE可以支持Windows上的各种开发工具,例如:Visual C,Visual Basic,Power Builder,Delphi,C+Builder,Lotus Notes,Internet Explorer等。下面是Visual Basic的例子(PowerBuilder和Delphi的客户程序几乎可以照搬这段代码):Sub main()Dim oEc As ObjectDim r% Set oEc = CreateObject("EasyCics.App")A r = oEc.Conn

7、ectServer("CICSNT01", "TEST", "TEST")B oEc.CallProgramAndCommit "GETTIME"C MsgBox oEc.GetValue("TIME")DEnd Sub清单 2-1-4以下是运行结果:图 2-1-13、如果使用JAVA,可以无须重新编译地移植您的程序。下面是JAVA的例子:import easycics.*;public class GetTimestatic public void main( String astrArg )

8、tryApp oEc = new easycics.App();/AoEc.ConnectServer("CICSNT01", "TEST", "TEST");/BoEc.CallProgramAndCommit("GETTIME");/C/Dcatch(ServerErrorException se)/E清单 2-1-6以下是运行结果:D:cics>java GetTimeSat Jan 29 21:22:16 2000清单 2-1-7我还能罗列出一大堆编程工具访问CICS的源码,是的,它们非常类似。您可能

9、注意到了GetValue、SetValue、ConnectServer、CallProgramAndCommit,是的,记住这些就差不多了,常用的调用很少,使用CICS确实非常简单。我们先来分析一下服务程序,就是清单2-1-1展示的C程序。这个程序采用的接口方法叫做EasyCICS,所以我们引入了“easycics.h”头文件,上面列举的那些函数都是EasyCICS的函数。InitEasyCics函数的作用是初始化环境,如果返回值非零,表示初始化失败。ExitEasyCics函数的作用是退出CICS服务程序,并把返回信息传给客户程序。注意,任何情况下退出CICS服务程序,必须调用ExitEas

10、yCics函数,或与其相当的CICS API,不能使用操作系统调用exit或_exit等。程序在A处的意思是,如果初始化失败,就退出CICS服务程序。程序在B处调用了BeginWrite函数,表示开始写通信用的公共数据区,它的真正作用是清除该公共数据区。程序在C处调用了SetValue函数,其作用是把一个字符串作为值赋予一个关键字(也是一个字符串),并存储在公共数据区。在这里,”TIME”是关键字,日期和时间字符串(由asctime函数获得)是值。这样做的意义何在?我们可以把很多值赋予不同的关键字,只要根据关键字就可以取出这些值。于是,客户机和服务器就可以利用这种方法进行通信。程序在D处调用了

11、ExitEasyCics函数,任何情况下退出CICS服务程序,必须调用该函数。只有C源程序还不够,我们还需要把它编译成执行文件或库文件(在Windows NT系统,CICS服务程序最终要被编译成为.DLL文件,即动态连接库)。一些程序员习惯于使用集成编译工具,但无法使用在UNIX等操作系统。我们采用更加通用的makefile方式进行编译。以下是在NT系统中,编译GETTIME服务程序的makefile(在各种UNIX系统,要进行必要的修改):gettime.dll: gettime.ccsset USERLIB=easycics.objcicstcl -e -d -lC gettime.ccs

12、清单 2-1-8如果您使用的是CICS for Windows NT,您可以使用图形界面把编译好的程序(gettime.dll)加入CICS域(region)。请参照如下插图:图 2-1-2 (选择管理界面程序)图 2-1-3 (在CICS域中选择program资源设置)图 2-1-4 (program资源设置)图 2-1- 5(program资源设置)当然,也可以使用如下指令(注意大小写):cicsadd -c pd -r CICS域名 你的程序名(GETTIME) PathName=路径 RSLKey=public再看看ANSI C的客户程序,就是清单2-1-2展示的C程序。这个程序采用的

13、接口方法也是EasyCICS,所以我们引入了“ec.h”头文件(注意服务程序使用的是叫做“easycics.h”的头文件)。程序在A处执行了ConnectServer函数。该函数的第一个参数是CICS的系统名称,相当于CICS域(Region)的连接字符串;函数的后两个参数分别是CICS的用户名称和口令。程序在B处执行了CallProgramAndCommit函数,我们一般使用此函数来调用服务程序(Program)。该函数的唯一参数就是要调用的CICS的服务程序名称,在此处,即GETTIME程序。程序在C处执行了GetValue函数,此函数通过其参数指定的关键字来获取服务器方面通过SetVal

14、ue函数来设置的字符串值。注意,可以通过多个SetValue和GetValue函数来传递多个字符串值。另外,如果客户机方面调用SetValue函数,而服务器方面调用GetValue函数也完全可以。SetValue和GetValue函数对是EasyCICS传递值的标准方法之一。这个客户程序的makefile如下:all: gettime.exegettime.exe: gettime.objlink gettime.obj ec.obj cclwin32.libgettime.obj: gettime.ccl -c gettime.c清单 2-1-9再看看使用Visual Basic的客户程序,

15、就是清单2-1-4展示的程序。这个程序采用EasyCICS组件。使用面向对象的术语,我们将反复提到组件的“方法”,或接口的“方法”,而不能说组件或接口的函数。程序在A处调用了VB的函数CreateObject创建了连接EasyCICS的对象。程序在B处执行了组件的ConnectServer方法。该方法的第一个参数是CICS的系统名称,相当于CICS域(Region)的连接字符串;函数的后两个参数分别是CICS的用户名称和口令。程序在C处执行了组件的CallProgramAndCommit方法,我们一般使用此函数来调用服务程序(Program)。该函数的唯一参数就是要调用的CICS的服务程序名称

16、,在此处,即GETTIME程序。程序在D处执行了组件的GetValue方法,此函数通过其参数指定的关键字来获取服务器方面通过SetValue函数来设置的字符串值。注意,可以通过多个SetValue和GetValue函数来传递多个字符串值。另外,如果客户机方面调用SetValue函数,而服务器方面调用GetValue函数也完全可以。SetValue和GetValue函数对是EasyCICS传递值的标准方法之一。Visual Basic不需要makefile之类的东西,可见使用组件是多么的简单。我们在PowerBuilder和Delphi中,都是通过组件访问CICS。最后,我们研究一下JAVA的例

17、子。JAVA通过GateWay来访问CICS Client,我们也可以采用EasyCICS,所以,我们首先引入了easycics.*,这为我们访问CICS Client奠定了基础。程序在A处创建了easycics.App的类实例对象。程序在B处执行了类的ConnectServer方法。该方法的第一个参数是CICS的系统名称,相当于CICS域(Region)的连接字符串;函数的后两个参数分别是CICS的用户名称和口令。程序在C处执行了类的CallProgramAndCommit方法,我们一般使用此函数来调用服务程序(Program)。该函数的唯一参数就是要调用的CICS的服务程序名称,在此处,即

18、GETTIME程序。程序在D处执行了类的GetValue方法,此函数通过其参数指定的关键字来获取服务器方面通过SetValue函数来设置的字符串值。注意,可以通过多个SetValue和GetValue函数来传递多个字符串值。另外,如果客户机方面调用SetValue函数,而服务器方面调用GetValue函数也完全可以。SetValue和GetValue函数对是EasyCICS传递值的标准方法之一。JAVA也不需要makefile之类的东西,而且可以不用重新编译,就移植到各种操作系统平台上。也许您对对上面介绍的示例程序GETTIME不以为然,因为它太简单了。那么,下面将介绍另一个示例程序TELEC

19、OM,一个同样简单但功能健全的标准示例程序。您可以通过这个程序,清晰地掌握CICS实现三层C/S结构的机制。之所以我把这个程序称为EasyCICS的标准示例,是因为所有编程工具的EasyCICS演示程序都有这个称为TELECOM的例子。那么,这个例子实现什么功能?TELECOM的客户程序向服务程序提供一个移动电话设备号码,服务程序根据这个号码查出相关的计费单据后返回给客户程序,客户程序立即显示此单据。整个过程都是在线同步执行,这也是一个OLTP的典型例子。以下是C语言作的CICS服务程序的清单(注意,这个源程序可以不加修改的运行在支持CICS的各种操作系统平台上):/*/*- HEADER F

20、ILES -*/#include "easycics.h"/*/*- DEFINES -*/#ifdef _WIN32#define DLLIMPORT _declspec(dllimport)#define DLLEXPORT _declspec(dllexport)#define CDECL _cdecl#else#define DLLIMPORT#define DLLEXPORT#define CDECL#endif/* #define either ORA or DB2 here */#define DB2#define SQLNOTFOUND 100#if def

21、ined ( DB2 )#include <sql.h>#elif defined ( ORA )#define SQLNOTFOUND 1403#endif/*/*- Global Variables -*/EXEC SQL INCLUDE sqlca; EXEC SQL BEGIN DECLARE SECTION;char Usr_name61;char Dev_no9; long Call_flg; char Called_arno11;char Called_no15;char Call_dat21;double Call_dur; double Call_rate; do

22、uble Call_fee; double Add_fee;char as_dev_no9; EXEC SQL END DECLARE SECTION;/*/*Functions*/*/* */void GetValueNum(char *Key, char *Value, int Num)char s4096;GetValue( Key, s );strncpy(Value,s,Num);ValueNum-1 = '0'/* */void main()char statusbuf1024, s30;if( InitEasyCics() ) ExitEasyCics();/*R

23、ead:*/GetValueNum( "NO", as_dev_no, sizeof(as_dev_no) );/*Write:*/BeginWrite();SetValue( "VER", "Telecom 1.0");RsCreate(10);RsSetColNameList("Usr_name,Dev_no,Call_flg,Called_arno,Called_no,Call_dat,Call_dur,Call_rate,Call_fee,Add_fee");/*可省略*/EXEC SQL DECLARE

24、c1 CURSOR FOR SELECT bas_infot.Usr_name, auto10a_list.Dev_no, auto10a_list.Call_flg, auto10a_list.Called_arno, auto10a_list.Called_no, auto10a_list.Call_dat, auto10a_list.Call_dur, auto10a_list.Call_rate, auto10a_list.Call_fee, auto10a_list.Add_fee FROM auto10a_list, bas_infotWHERE ( auto10a_list.De

25、v_no = bas_infot.Dev_no ) AND auto10a_list.Dev_no = :as_dev_no;sprintf(statusbuf,"declear cursor code=%dn", sqlca.sqlcode);PrintStatus(statusbuf);EXEC SQL OPEN c1;sprintf(statusbuf,"open cursor code=%dn", sqlca.sqlcode);PrintStatus(statusbuf);doEXEC SQL FETCH c1 INTO :Usr_name, :

26、Dev_no, :Call_flg, :Called_arno, :Called_no, :Call_dat, :Call_dur, :Call_rate, :Call_fee, :Add_fee;sprintf(statusbuf,"fetch code=%dn", sqlca.sqlcode);PrintStatus(statusbuf);if( (sqlca.sqlcode = SQLNOTFOUND) | (sqlca.sqlcode <0) )break;elseRsAddRow();sprintf( statusbuf, "%s,%s,%d,%s

27、,%s,%s,%7.0f,%8.3f,%7.2f,%6.2fn", Usr_name, Dev_no, Call_flg, Called_arno, Called_no, Call_dat, Call_dur, Call_rate, Call_fee, Add_fee );PrintStatus(statusbuf);RsSetCol( 1, Usr_name );RsSetCol( 2, Dev_no );sprintf( s, "%lu", Call_flg );RsSetCol( 3, s );RsSetCol( 4, Called_arno );RsSet

28、Col( 5, Called_no );RsSetCol( 6, Call_dat );sprintf( s, "%6.2f", Call_dur );RsSetCol( 7, s );sprintf( s, "%6.2f", Call_rate );RsSetCol( 8, s );sprintf( s, "%6.2f", Call_fee );RsSetCol( 9, s );sprintf( s, "%6.2f", Add_fee );RsSetCol( 10, s );RsSaveRow();while(1

29、);EXEC SQL CLOSE c1; /*#ifdef( SYBASE )EXEC SQL DEALLOCATE CURSOR c1;#endif*/sprintf(statusbuf,"close cursor code=%dn", sqlca.sqlcode);PrintStatus(statusbuf);ExitEasyCics();清单 2-1-10 (telecom.sqc)这是个典型的E-SQL程序(在ORACLE中叫PROC),如果您不熟悉E-SQL编程,不用着急,本书有详细的说明。由于后面的内容有对本程序的详细分析,这里仅简要说明一下程序的流程。如果不特

30、别注重程序的移植性、健壮性和调试信息,可以把清单2-1-10的程序简化成下面的程序:#include "easycics.h"#include <sql.h>#define SQLNOTFOUND 100EXEC SQL INCLUDE sqlca; EXEC SQL BEGIN DECLARE SECTION;char Usr_name61;char Dev_no9; long Call_flg; char Called_arno11;char Called_no15;char Call_dat21;double Call_dur; double Call_r

31、ate; double Call_fee; double Add_fee;char as_dev_no9; EXEC SQL END DECLARE SECTION;/* */void main()char s30;if( InitEasyCics() ) ExitEasyCics();/*Read:*/GetValue ( "NO", as_dev_no );/*Write:*/BeginWrite();RsCreate(10);RsSetColNameList("Usr_name,Dev_no,Call_flg,Called_arno,Called_no,Ca

32、ll_dat,Call_dur,Call_rate,Call_fee,Add_fee");/*可省略*/EXEC SQL DECLARE c1 CURSOR FOR SELECT bas_infot.Usr_name, auto10a_list.Dev_no, auto10a_list.Call_flg, auto10a_list.Called_arno, auto10a_list.Called_no, auto10a_list.Call_dat, auto10a_list.Call_dur, auto10a_list.Call_rate, auto10a_list.Call_fee

33、, auto10a_list.Add_fee FROM auto10a_list, bas_infotWHERE ( auto10a_list.Dev_no = bas_infot.Dev_no ) AND auto10a_list.Dev_no = :as_dev_no;EXEC SQL OPEN c1;doEXEC SQL FETCH c1 INTO :Usr_name, :Dev_no, :Call_flg, :Called_arno, :Called_no, :Call_dat, :Call_dur, :Call_rate, :Call_fee, :Add_fee;if( (sqlca

34、.sqlcode = SQLNOTFOUND) | (sqlca.sqlcode <0) )break;elseRsAddRow();RsSetCol( 1, Usr_name );RsSetCol( 2, Dev_no );sprintf( s, "%lu", Call_flg );RsSetCol( 3, s );RsSetCol( 4, Called_arno );RsSetCol( 5, Called_no );RsSetCol( 6, Call_dat );sprintf( s, "%6.2f", Call_dur );RsSetCol(

35、 7, s );sprintf( s, "%6.2f", Call_rate );RsSetCol( 8, s );sprintf( s, "%6.2f", Call_fee );RsSetCol( 9, s );sprintf( s, "%6.2f", Add_fee );RsSetCol( 10, s );RsSaveRow();while(1);EXEC SQL CLOSE c1; ExitEasyCics();清单 2-1-11 (简化telecom.sqc)清单2-1-11所示的程序可以用于CICS for NT,访问DB2

36、数据库。我们来简单分析一下简化的telecom.sqc程序:这个程序采用的接口方法是EasyCICS,所以引入了“easycics.h”头文件。 程序的开始声明了一些宿主变量(在EXEC SQL BEGIN DECLARE SECTION;和EXEC SQL END DECLARE SECTION;之间),所谓“宿主变量”即可以同时用于C语言变量和SQL变量。注意,以EXEC SQL打头的语句都可以通过数据库的预编译程序转化成相应的C语言代码。在执行部分,程序首先调用InitEasyCics函数来初始化环境。接着调用GetValue函数,此函数通过其参数指定的关键字“NO”来获取客户机方面通过

37、SetValue函数来设置的字符串值。再调用了BeginWrite函数,表示开始写通信用的公共数据区,它的真正作用是清除该公共数据区。接着调用了几个以“Rs”为字头的函数,表示要设置结果集(ResultSet)。函数RsCreate表示要创建结果集,其参数是结果集的列数。函数RsSetColNameList设置结果集各列的名称,如果客户机仅通过相对位置来获取各列的值(这样效率更高),则可以省略此调用。接着程序声明并打开SQL游标,并在一个循环中不断获取数值存入宿主变量,直到游标最后结束(sqlca.sqlcode=SQLNOTFOUND)或出错(sqlca.sqlcode <0)。注意每

38、从数据库取出一行,调用RsAddRow函数使EasyCICS的结果集增加一行。取到宿主变量中的数值可以再通过RsSetCol函数写到EasyCICS的结果集中,注意此函数的第一个参数是列序号(从1开始),第二个参数是字符串值(EasyCICS只接受字符串值)。各列写完之后,要调用RsSaveRow函数存储此行数据。程序最后在关闭游标后调用了ExitEasyCics函数,注意在任何情况下退出CICS服务程序,必须调用该函数。只有C源程序还不够,我们还需要把它编译成执行文件或库文件(在Windows NT系统,CICS服务程序最终要被编译成为.DLL文件,即动态连接库)。一些程序员习惯于使用集成编

39、译工具,但无法使用在UNIX等操作系统。我们采用更加通用的makefile方式进行编译。以下是在NT系统中,编译TELECOM服务程序的makefile(在各种UNIX系统,要进行必要的修改):all: telecom.dll telecom.ccs: telecom.sqcdb2 connect to cicstestdb2 prep telecom.sqc bindfiledb2 bind telecom.bnddb2 grant execute on package telecom to publicdb2 connect resetcopy telecom.c telecom.ccs

40、telecom.dll: telecom.ccsset CICS_MSC_FLAGS=-I$(DB2PATH)includeset USERLIB=$(DB2PATH)libdb2api.lib easycics.objcicstcl -e -d -lC telecom.ccsclean:del telecom.bnd telecom.c telecom.ccs telecom.dll telecom.exp telecom.lib telecom.obj清单 2-1-12再看看ANSI C的客户程序,就是清单2-1-13展示的C程序。#include "ec.h"/* *

41、/void main()int i, j, rc, cc, r;char s100, c, cr;r= ConnectServer( "CICSNT01", "TEST", "TEST" );printf( "Connect Code: %dn", r );printf("Enter Query Number:");scanf( "%s", s );scanf( "%c", &cr );BeginWrite();SetValue( "NO

42、", s );r= CallProgramAndCommit("TELECOM");if(r)puts("Call Program Error !");return;RsOpen();rc = RsGetRowNum();cc = RsGetColNum();for( i=1; i<=rc; i+ )RsFetchRow(); for(j=1; j<cc; j+)RsGetCol(j,s);printf(s);printf( "," ); puts("");清单 2-1-13以下是运行结果(按

43、提示输入查询的号码,程序返回查询的结果):D:cics>testecConnect Code: 0Enter Query Number:2020088宋阮,2020088,105011031,0595,01385995193,Apr 17 1999 10:55PM , 3.00, 1.00, 1.50,宋阮,2020088,105011031,0595,01385990145,Apr 16 1999 12:22PM , 1.00, 1.00, 1.00,宋阮,2020088,105011031,0595,01385922328,Apr 9 1999 6:42PM , 1.00, 1.00

44、, 1.00,宋阮,2020088,105011031,0595,01385922328,Apr 7 1999 12:50PM , 2.00, 1.00, 2.00,宋阮,2020088,105011031,0595,01385995193,Apr 6 1999 12:57PM , 3.00, 1.00, 3.00,宋阮,2020088,105011031,0595,01385995193,Apr 5 1999 11:29AM , 1.00, 1.00, 1.00,宋阮,2020088,105011031,0595,01385995193,Apr 5 1999 10:08AM , 1.00,

45、1.00, 1.00,宋阮,2020088,105011031,0595,01385995193,Apr 3 1999 3:50PM , 4.00, 1.00, 2.00,宋阮,2020088,105011031,0595,01385995183,Apr 3 1999 10:15AM , 1.00, 1.00, 0.50,宋阮,2020088,105011031,0595,01385995193,Mar 31 1999 9:48PM , 6.00, 1.00, 3.00,宋阮,2020088,105011031,0595,01385995193,Mar 29 1999 4:49PM , 5.0

46、0, 1.00, 5.00,宋阮,2020088,105011031,0595,01385995193,Mar 27 1999 3:03PM , 9.00, 1.00, 4.50,宋阮,2020088,105011031,0595,01385995193,Mar 21 1999 10:48PM , 3.00, 1.00, 1.50,清单 2-1-14这个程序采用的接口方法也是EasyCICS,所以我们引入了“ec.h”头文件(注意服务程序使用的是叫做“easycics.h”的头文件)。程序首先执行了ConnectServer函数。该函数的第一个参数是CICS的系统名称,相当于CICS域(Reg

47、ion)的连接字符串;函数的后两个参数分别是CICS的用户名称和口令。接着根据用户输入的号码调用SetValue函数,其作用是把一个字符串作为值赋予一个关键字(也是一个字符串),并存储在公共数据区。在这里,”NO”是关键字。注意所谓关键字是用户随意定义的,但最好客户程序和服务程序能相互匹配,如果没有通过SetValue函数设置某关键字的值就直接调用GetValue函数取此关键字的值,则取出空字符串。再下面程序执行了CallProgramAndCommit函数,我们一般使用此函数来调用服务程序(Program)。该函数的唯一参数就是要调用的CICS的服务程序名称,在此处,即TELECOM程序。接

48、下来程序调用了一些结果集函数(以“Rs”为字头)。RsOpen函数用于打开结果集。注意,RsCreate和RsOpen函数对是EasyCICS传递二维值的标准方法,而SetValue和GetValue函数对是EasyCICS传递单值(零维值)的标准方法。结果集的行数和列数可以通过函数RsGetRowNum 和RsGetRowNum得到。函数RsFetchRow用于取出结果集的一行,而函数RsGetCol用于取出当前行的一列值。所有返回的值经格式化后写到屏幕上。这个客户程序的makefile如下:all: testec.exetestec.exe: testec.objlink testec.o

49、bj ec.obj cclwin32.libtestec.obj: testec.ccl /c testec.c清单 2-1-15下面是Visual Basic客户程序的源代码:Option ExplicitDim oEc As New EasyCics.AppPrivate Sub btnAbout_Click() oEc.AboutEnd SubPrivate Sub btnQuery_Click()Dim r%, s$, i%, j%, rc%, cc% lstTest.Clear oEc.BeginWrite s = txtNo.Text oEc.SetValue "NO&q

50、uot;, s oEc.CallProgramAndCommit "TELECOM" s = oEc.GetErrIf s <> "" Then MsgBox "Got an error when call CICS Server program:" + Chr(13) + Chr(10) + s Exit SubEnd If oEc.RsOpen rc = oEc.RsGetRowNum cc = oEc.RsGetColNum s = ""For i = 1 To rc oEc.RsFetchRow

51、 For j = 1 To cc s = s + oEc.RsGetCol(j) + "," Next lstTest.AddItem s s = ""Next End SubPrivate Sub Form_Load()Dim r% r = oEc.ConnectServer("CICSNT01", "TEST", "TEST")If r <> 0 Then MsgBox "Can't connect" Exit SubEnd IfEnd SubPriv

52、ate Sub Form_Unload(Cancel As Integer) Set oEc = NothingEnd Sub清单 2-1-16Visual Basic程序采用EasyCICS组件(PowerBuilder和Delphi也是通过组件访问CICS)。使用面向对象的术语,我们将反复提到组件的“方法”,或接口的“方法”,而不能说组件或接口的函数。程序预先创建了连接EasyCICS的对象。程序首先执行了组件的ConnectServer方法。该方法的第一个参数是CICS的系统名称,相当于CICS域(Region)的连接字符串;函数的后两个参数分别是CICS的用户名称和口令。接着根据用户输入的到文本框中的号码调用了组件的SetValue方法,其作用是把一个字符串作为值赋予一个关键字(也是一个字符串),并存储在公共数据区。在这里,”NO”是关键字。注意所谓关键字是用户随意定义的,但最好客户程序和服务程序能相互匹配,如果没有通过SetValue方法设置某关键字的值就直接调用GetValue

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论