tuxedo的客户端与服务端之间的数据传送是通过数据缓冲区来进行的.TUXEDO的数据缓冲区主要包括STRING,CARRAY,VIEW,VIEW32,FML,FML32,从TUXEDO7.1开始,还增加了XML数据缓冲区.另外,TUXEDO还有几种缓冲区是专门针对COBAL的。在TUXEDO中还可以定义自己的缓冲区类型。
在TUXEDO中客户端与服务端之间进行数据交换的缓冲区(如:tpcall()中的输入,输出缓冲区等)都要用TUXEDO自己提供的API进行操作,不能采用C语言的函数如:malloc(),free()等分配,释放这些缓冲区。同时在程序中要自己管理这些缓冲区,象C语言中的缓冲区一样,在用tpalloc() 分配一块缓冲区之后,在不在需要该缓冲区时用tpfree()释放掉。
与缓冲区使用有关的ATMI
char * tpalloc(char *type, char *subtype, long size)
描述:分配缓冲区
参数:type:缓冲区的类型
subtype:缓冲区的子类型,只有VIEW有子类型,其他的缓冲区该参数要设为NULL
long:缓冲区的大小
返回值: 成功返回一个指向所分配空间首地址的CHAR *形指针,失败返回NULL。
char * tprealloc(char *ptr, long size)
描述:重新分配缓冲区
参数:ptr:指向原缓冲区首地址的指针
size:新缓冲区的大小
返回值: 成功返回一个指向新分配空间首地址的CHAR *形指针,失败返回NULL。
void tpfree(char *bufptr)
描述:释放由TPALLOC()或TPREALLOC()分配的缓冲区
参数:bufptr:指向要释放的缓冲区首地址的指针
返回值:无
注意: 用TPALLOC(),TPREALLOC()分配的内存只能有TPFREE()释放掉,不能用FREE()
long tptypes(char *ptr, char *type, char *subtype)
描述:返回有ptr所指向的缓冲区的类型及子类型
参数: ptr:指向要进行类型识别的缓冲区首地址的指针
type:类型名
subtype:子类型名(只对VIEW类型有效)
返回值:0成功,-1失败, 错误号保存在全局变量tperrno中。
下面我们对常用的数据缓冲区分别进行介绍
STRING:
类似于C中的CHAR *,是以\0接尾的字符串,如果两台机器之间的编码不一样(如一台为ASCII, 另一台为EBCDIC),TUXEDO 将自动进行编码/解码工作。 STRING一般用于在客户端与SERVER端之间传送文本数据。
CARRAY:
是不以\0接尾的字符串,长度要由用户指定。如果两台机器之间的编码不一样,也不进行编码/解码工作。注意在TPCALL,TPACALL,TPRETURN等ATMI中使用CARRY类型的缓冲区时,一定要指定长度,否则会出错。CARRY一般用于传送二进制数据。如在客户端与SERVER端之间传送一个二进制的文件,就要采用CARRAY类型的缓冲区。
VIEW(VIEW32)缓冲区
类似于C中的结构体,不同的是该结构的成员的数据类型可以为short, char, long, float, double,STRING ,CARRAY。 要在一个文件中定义该VIEW(VIEW32)的结构,然后才能使用。VIEW有子类型,子类型为该VIEW(VIEW32)的名字,在调用TPALLOC()分VIEW(VIEW32)缓冲区时要指定该子类型。
VIEW32与VIEW类似,但它采用32位长度的数表示结构体中字段的ID等,VIEW采用16位表示,所以VIEW32可表示更多的字段。
VIEW(VIEW32)缓冲区还可以转化为FML(FML32)缓冲区。
VIEW的使用过程:
1. 定义一个VIEW(VIEW32)的描述文件*.v,如下所示:定义一个名为aud的VIEW
VIEW aud
$ /* View structure for audit information */
# type cname fbname count flag size null
long b_id BRANCH_ID 1 - - 0
float balance BALANCE 2 - - 0.0
string ermsg STATLIN 3 - 80 ""
END
说明: 定义一个VIEW(VIEW32)类似于定义一张表,各个字段的含义如下:
type: 该字段的数据类型, 可以为short, char, long, float, double,STRING ,CARRAY.
Cname: 该字段的名字
Fbname: VIEW(VIEW32)可以转化为FML(FML32), 该字段指定如果该VIEW(VIEW32)可以转化
为FML(FML32)时,相应字段的名字。
Count: 该字段的位置值
Flag: 设置该字段的一些标志,主要与转化为FML(FML32)有关
Size: 该字段的长度,只对STRING,CARRY有用
Null: 如果该字段为空(没有被赋值时)时的默认值。如果没有指定,那么数字型的为0,字符型的为"\0",CARRY型的为””。
$: 注释,并且出现在生成的*.h文件中
#: 注释,不出现在生成的*.h文件中
“-”: 表示该属性采用默认值.
2. 用VIEWC(VIEWC32 )进行编译,生成对应的*.h文件和*.VV文件:viewc –n aud
3. 定义环境变量VIEWDIR(VIWEDIR32),VIEWFILES(VIEWFILES32)
VIEWDIR(VIEWDIR32): VIEW(VIEW32)的定义文件所在的路径
VIEWFILES(VIEWFILES32): VIEW(VIEW32)的定义文件名,如果有多个用,隔开
4. 在使用到该VIEW(VIEW32)的程序中用#include包含生成的*.h文件.
5.在程序中可以象使用C语言的结构体一样使用该VIEW(VIEW32)
VIEW(VIEW32)的使用例子:
在客户端通过一个VIEW缓冲区把数据传送到服务器端,在服务器端把收到的数据打印出来。
1.定义VIEW的定义文件aud.v
VIEW aud
$ /* View structure for audit information */
# type cname fbname count flag size null
long b_id BRANCH_ID 1 - - 0
float balance BALANCE 2 - - 0.0
string ermsg STATLIN 3 - 80 ""
2.用viewc -n aud.v 进行编译,生成对应的aud.h文件和aud.VV文件.
aud.h文件的内容如下, aud.VV为二进制的文件
struct aud {
/* View structure for audit information */
long b_id;
float balance;
char ermsg[80];
};
3. 定义环境变量VIEWDIR,VIEWFILES
set VIEWFILES=aud.VV
set VIEWDIR=%APPDIR%
4. 客户端的程序client.c:
#include <stdio.h>
#include "atmi.h"
#include "aud.h"
#include "fml.h"
main(int argc, char **argv)
{
struct aud *audv;
FBFR *rcvbuf;
long rcvlen;
char * str_buf = "";
int ret;
if (tpinit((TPINIT *) NULL) == -1)
{
printf("Tpinit failure: %s\n",tpstrerror(tperrno));
exit(1);
}
if ((audv = (struct aud *)tpalloc("VIEW", "aud", sizeof(struct aud))) ==(struct aud *)NULL)
{
printf("tpalloc(VIEW) failure: %s\n",tpstrerror(tperrno));
exit(1);
}
rcvbuf = tpalloc("STRING", NULL, 1000);
audv->balance = 110.0;
strcpy(audv->ermsg,"this is a view test");
/* Request the service TOUPPER, waiting for a reply */
if(tpcall("VIEWDEMO", (char *)audv, sizeof(struct aud), (char **)&audv,&rcvlen, (long)0)==-1)
{
printf("tpcall(TOUPPER) failure:%s\n",tpstrerror(tperrno));
tpfree(audv);
tpfree(rcvbuf);
tpterm();
exit(1);
}
tpfree(audv);
tpfree(rcvbuf);
tpterm();
}
服务端的程序server.c如下:
include <stdio.h>
#include <atmi.h>
#include <userlog.h>
#include "aud.h"
TOUPPER(TPSVCINFO *rqst)
{
struct aud *audv;
audv = (struct aud *)rqst->data;
userlog("balance=%f\n",audv->balance);
userlog("ermsg=%s\n",audv->ermsg);
tpreturn(TPSUCCESS, 0, NULL, 0, 0);
}