分类:
2009-07-08 20:20:25
为了更好的了解客户端的所有任务以编写客户端应用,有必要重新认识客户端在C/S模式中扮演的角色。
首先,客户端是用户界面。意思是当用户在系统上用程序进行一次操作的整个过程就是一个客户端过程。前端过程是对客户端的另一个描述。客户端的首要任务就是获得执行操作应该得到的数据。
一旦客户端得到了应有的信息,应该将数据按服务能够识别并适合传输的格式打包。
然后,向服务端发送请求并等待回应。
收到回应数据后,将其按一定格式返回给终端用户。
客户端程序的设计和实现可以被分成2部分考虑:
² 用户处理过程
² TUXEDO功能部分
下文的客户端程序只描述了TUXEDO功能部分。
利用TUXEDO的ATMI API调用可以做到:
——基本的TUXEDO调试技巧(tperrno,tpstrerror,userlog)
——TUXEDO进程管理(tpinit,tpterm)
——基本数据缓冲管理(tpalloc,tprealloc,tpfree)
——基本通讯(tpcall,tpacall,tpgetrply)
当调用ATMI出错时,返回值为-1,全程变量tperrno被设值,该变量提供系统定义的出错原因。函数tpstrerror()以此变量为参数,返回错误的字符说明信息。
完整的错误号和文本错误信息存在于文件$TUXDIR/include/atmi.h。
函数userlog()重定向输出文件为ULOG.mmddyy。使用方法同printf()。该函数每次输出都写硬盘,这样在系统失败时也能保留调试信息。
代码范例
main()
{
int ret;
ret = [a ATMI call]
if ( ret == -1 )
{
printf(“Error in ATMI call\n”);
usrlog(“ATMI error logged %d %s”,tperrno,tpstrerror(tperrno));
}else
printf(“ATMI call OK\n”);
……
ret = tpterm();
if ( ret == -1 )
{
printf(“Error in exiting application\n”);
usrlog(“ATMI error logged %d %s”,tperrno,tpstrerror(tperrno));
}
}
tperrno – 全程变量
(char *)tpstrerror(int)
userlog(…) – 语法同printf()
ULOG.mmddyy – 日志文件
为了使客户端能够访问TUXEDO交易,客户端程序必须连接TUXEDO应用并进行登记。这种管理性步骤在切断连接时也要类似执行一次。API如下:
int tpinit(TPINIT *tpinfo)
客户端通过调用tpinit()与应用连接,进行交互,有以下事件发生:
调用安全接口检查客户端是否需要认证
连接BB,使进一步的ATMI函数得到信息
使BBL了解BB中已经存在请求
建立客户端消息队列使服务可以发回返回信息,系统可以送出广播通知等
错误时返回-1,可能由以下原因引起:
² TPEINVAL 参数错误
² TPENOENT BB无空间
² TPEPERM 无连接权限
² TPEPROTO 协议错误 – 被服务调用
int tpterm()
客户端调用tpterm()切断与应用的连接,结束了客户端的TUXEDO进程,该过程发生以下事件:
BB入口删除,使BBL知道客户端已经离开
客户端离开BB,客户端的信号量被移除
客户端消息队列被移除
错误时返回-1,可能由以下原因引起:
TPEPROTO 协议错误 – 被服务调用
TPESYSTEM /T系统下错误
TPEOS 操作系统错
范例
main()
{
int ret;
ret=tpinit((TPINIT *)NULL);
……
ret=tpterm();
}
ATMI提供函数分配(tpalloc(),tprealloc())、释放(tpfree())TUXEDO数据缓冲。应用负责将应用数据填入缓冲。应用的数据类型和组织决定应该选择何种数据缓冲。函数type()可以返回正在使用的数据缓冲类型。
以下是TUXEDO基本的数据缓冲类型:
² STRING 以空值结尾的单域字符数据。
² CARRAY 有长度定义的单域二进制数据,不进行编、解码。
² VIEW 类C结构或COBOL记录的多域组织。
² FML 无固定结构的自定义缓冲。
tpalloc(),tprealloc()在出错时返回空值,可能由以下原因引起:
² TPEOS 操作系统
² TPEINVAL 非法或不正确的类型
² TPESYSTEM TUXEDO之下的错误
范例
main()
{
int ret;
char *bufptr;
ret = tpinit((TPINIT *)NULL);
if ( ret == -1)
{
printf(“Error in joining application\n”);
userlog(“tpinit error %d %s”,tperrno,tpstrerror(tperrno));
}else
printf(“tpinit ok\n”);
bufptr=tpalloc(“STRING”,NULL,1*1024);
if ( bufptr==NULL)
{
printf(“Error in allocating buffers \n”);
userlog(“tpinit error %d %s”,tperrno,tpstrerror(tperrno));
tpterm();
exit(-1);
}
……
tpfree(bufptr);
ret = tpterm();
if ( ret == -1)
{
printf(“Error in exiting application\n”);
userlog(“tpterm error %d %s”,tperrno,tpstrerror(tperrno));
}
}
函数用法
(char *)tpalloc((char *)type,(char *)subtype,long size)
(char *)tprealloc((char *)bufptr,long newsize)
void tpfree((char *)bufptr)
函数tpcall()有6个参数。如下:
² 交易名
² 请求数据缓冲
² 请求数据缓冲的长度(仅缓冲类型为CARRY时需要)
² 返回数据缓冲的地址。缓冲大小可以根据收到数据而改变。
² 返回数据缓冲大小的地址
² 标志量
标志量可以是以下值:
² TPNOTRAN 如有交易不调用
² TPNOBLOCK 如有阻塞不等待
² TPNOTIME 愿意等待直到超时
² TPSIGRSTRT 系统中断信号在TUXEDO完成后再发布
出错返回-1,错误原因如下:
² TPEINVAL 参数错误
² TPETRAN 交易相关错误
² TPETIME 超时
代码范例
main()
{
int ret;
long len=0,flags=0;
char *bufptr;
if (tpinit((TPINIT * )NULL) == -1)
{
exit(1);
}
if ((buf=tpalloc(“STRING”,NULL,801*1024==NULL)
{
tpterm();
exit(2);
}
ret = tpcall(“TOUPPER”,bufptr,len,&bufptr,&len,flags);
if (ret == -1)
{
userlog(“Error requesting %d %s”,tperrno,tpstrerror(tperrno));
tpfree(bufptr);
exit(-2);
}
tpfree(bufptr);
if(tpterm()== -1)
{
userlog(“tpterm error %d %s”,tperrno,tpstrerror(tperrno));
}
}
int tpcall((char *)servicename,(char *)bufptr,long length,(char **)bufptr,(long *)length,long flags)
ATMI提供2个异步通讯函数
² tpacall()
² tpgetrply()
tpacall()有4个参数
² 交易名
² 请求数据缓冲
² 请求数据缓冲的长度(仅缓冲类型为CARRY时需要)
² 标志量(同tpcall())
返回值是一个非负描述符(句柄),用于其后的tpgetrply()调用。如果tpacall()调用失败,句柄是-1,错误原因设置在tperrno,可能是以下值:
² TPELIMIT 过多未处理的tpacall()
² TPETIME 超时
tpacall()后总跟随一个tpgetrply(),有4个参数
² 变量地址,可以传入tpcall()所得句柄,或另设一个
² 返回数据缓冲的地址。缓冲大小可以根据收到数据而改变。
² 返回数据缓冲大小的地址
² 标志量
标志量的值可以是如下之一:
² TPGETANY 取第一个返回值,设句柄
² TPNOCHANGE 取发送请求的匹配的类型的信息
² 参见tpcall()中的值
返回值0表示成功,-1表示失败,错误原因可能如下:
² TPEINVAL 参数错误
² TPEOTYPE 返回数据缓冲类型错误
² TPETIME 超时
main()
{
if (tpinit((TPINIT *)NULL)== -1)
……
bufptr=tpalloc(“STRING”,NULL,100);
if (bufptr==NULL)
……
cd=tpacall(“TOUPPER”,bufptr,len,flags);
if (tpgetrply(&cd,&bufptr,&len,flags)== -1)
……
tpfree(bufptr);
if (tpterm()== -1)
……
}
int tpacall((char *)service,(char *)bufptr,long len,long flags);
flag:TPNOBLOCK,TPSIGRSTRT,TPNOTIME,TPNOTRAN,TPNOCHANGE,TPGETANY
int tpgetrply((int *)handle,(char **)bufptr,(long *)len, long flags);
flag:TPNOBLOCK,TPSIGRSTRT,TPNOTIME,TPNOTRAN
当C语言的客户端程序编码完后,需要连接正确的库并编译。使用buildclient可以使该过程容易一点。该命令引用了C语言编译器并按正确的次序连接TUXEDO系统的库。为使用buildclient,应确认客户端程序包含了”atmi.h”,TUXDIR被设了正确的值。命令语法如下:
buildclient [-v] –o executable –f first-file [-f first-file] [-l last-file]
此处first-file表示的应该是编译器可以识别的文件。缺省的编译器是cc。一般是.c(c源程序),.C(C++源程序),.o(object)或.a(库)文件。
参数解释如下:
-o 生成的可执行文件名
-f 需要在连接TUXEDO库之前传给编译器的文件名。如有多于一个的文件名,名字应用空格分隔并用引号引起。也可以使用多个-f参数。
-l 需要在连接TUXEDO库之前传给编译器的文件名。语法同上。
-v 编译过程显示。
l 不同的客户端/服务器模式
l 用TUXEDO管理多层客户端/服务器模式
l 一个简单应用:simpapp
l 开发TUXEDO客户端