学习了FML后,自己练手写了一个tuxedo FML32服务器端和客户端程序,供大家参考
本例是在Redflag DC server 5.0上,使用的是tuxedo9.1,从本地读取一个文件tlr.txt,然后把文件内容以FML32缓冲区方式发送到服务器,由服务器处理后,返回内容增加一个序号。文件内容为:[hwt@localhost fml]$ cat tlr.txt
hwt 29 18677150924
lht 28 13398813422
csq 25 13234234564
服务器处理后,预期结果为:
[hwt@localhost fml]$ ./clientfml tlr.txt
hwt 29 18677150924 33
lht 28 13398813422 42
csq 25 13234234564 21
------------------------------------------------
步骤一:
设置环境变量:
[hwt@localhost fml]$ cat setenv.ksh
TUXDIR=/home/hwt/tux9.1/tuxedo9.1
PATH=$TUXDIR/bin:.:$PATH
export TUXDIR PATH
LD_LIBRARY_PATH=$TUXDIR/lib:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH
APPDIR=/home/hwt/fml
TUXCONFIG=$APPDIR/tuxconfig
FIELDTBLS32=fmlfile
FLDTBLDIR32=$APPDIR
export APPDIR TUXCONFIG FLDTBLDIR32 FIELDTBLS32
[hwt@localhost fml]$ . ./setenv.ksh
步骤二:
[hwt@localhost fml]$ cat UBBconfigunix
*RESOURCES
IPCKEY 155442
MAXACCESSERS 50
MAXSERVERS 25
MASTER SITE1
MODEL SHM
*MACHINES
"localhost"
LMID=SITE1
APPDIR="/home/hwt/fml"
TUXCONFIG="/home/hwt/fml/tuxconfig"
TUXDIR="/home/hwt/tux9.1/tuxedo9.1"
*GROUPS
MATHGRP LMID=SITE1
GRPNO=1
*SERVERS
serverfml SRVID=1
SRVGRP=MATHGRP
CLOPT="-A"
*SERVICES
编译UBB:
[hwt@localhost fml]$ tmloadcf -y UBBconfigunix
步骤三:
编写fmlfile文件,这里一定要注意了,字段必须大写,不然调试半天找不到错误原因的:
[hwt@localhost fml]$ cat fmlfile
*base 1000
NAME 1 string - -
AGE 2 long - -
PHONE 3 string - -
NO 4 long - -
编写完毕后,编译文件,会生成fmlfile.h:
[hwt@localhost fml]$ mkfldhdr fmlfile
[hwt@localhost fml]$ cat fmlfile.h
/* fname fldid */
/* ----- ----- */
#define NAME ((FLDID)41961) /* number: 1001 type: string */
#define AGE ((FLDID)9194) /* number: 1002 type: long */
#define PHONE ((FLDID)41963) /* number: 1003 type: string */
#define NO ((FLDID)9196) /* number: 1004 type: long */
步骤四:
编写客户端程序clientfml.c
程序代码:
#include <stdio.h> #include <string.h> #include "atmi.h" #include "fml32.h" #include "userlog.h" #include "fmlfile.h" int main(int argc, char *argv[]) { if(argc!=2){ (void)fprintf(stderr,"usage:%s filename\n",argv[0]); (void)exit(1); } FBFR32 *pF32,*pF32rec; long len; FLDLEN32 len2; typedef struct tlr { char name[10]; long age; char phone[12]; long no; }*pTLR; int counter,i,ret; FILE *fp; char *str1=(char *)malloc(100); fp=fopen(argv[1],"r"); if(fp==NULL){ (void)fprintf(stderr,"%s: file no found!\n",argv[1]); (void)exit(1); } if (tpinit((TPINIT *)NULL) == -1) { (void)fprintf(stderr, "Failed to join application -- %s\n", tpstrerror(tperrno)); (void)userlog("Clientfml failed to join application -- %s\n", tpstrerror(tperrno)); (void)fclose(fp); (void)exit(1); } if ((pF32 = (FBFR32 *)tpalloc("FML32", NULL, Fneeded32(1,30))) == NULL) { (void)fprintf(stderr, "Failure to allocate FML32 buffer -- %s\n", tpstrerror(tperrno)); (void)userlog("Clientfml failed to allocate FML32 buffer -- %s\n", tpstrerror(tperrno)); (void)tpterm(); (void)fclose(fp); (void)exit(1); } if ((pF32rec = (FBFR32 *)tpalloc("FML32", NULL, Fneeded32(1,32))) == NULL) { (void)fprintf(stderr, "Failure to allocate FML32 buffer -- %s\n", tpstrerror(tperrno)); (void)userlog("Clientfml failed to allocate FML32 buffer -- %s\n", tpstrerror(tperrno)); (void)fclose(fp); (void)tpterm(); (void)exit(1); } pTLR ptlr[3]; pTLR ptlr2[3]; for(i=0;i<3;i++){ ptlr[i]=(pTLR)malloc(sizeof(struct tlr)); if(ptlr[i]==NULL){ (void)fprintf(stderr,"mem allocate error!\n"); (void)fclose(fp); (void)exit(1); } ptlr2[i]=(pTLR)malloc(sizeof(struct tlr)); if(ptlr2[i]==NULL){ (void)fprintf(stderr,"mem allocate error!\n"); (void)fclose(fp); (void)exit(1); } } i=0; while(fgets(str1,100,fp)!=NULL){ if((ret=sscanf(str1, "%s %ld %s", ptlr[i]->name, &ptlr[i]->age, ptlr[i]->phone))<3){ (void)fprintf(stderr,"error in calling sscanf():%d\n",ret); (void)fclose(fp); (void)exit(1); } i++; } for(i=0;i<3;i++){ if (Fadd32(pF32,NAME, (char *)ptlr[i]->name, 0) == -1) { (void)fprintf(stderr, "Failure to change NAME field -- %s\n", Fstrerror32(Ferror32)); (void)userlog("Clientfml failed to change NAME field -- %s\n", Fstrerror32(Ferror32)); (void)tpfree((char *)pF32); (void)tpfree((char *)pF32rec); (void)free(str1); for(i=0;i<3;i++){ (void)free(ptlr[i]); (void)free(ptlr2[i]); } (void)fclose(fp); (void)tpterm(); (void)exit(1); } if (Fadd32(pF32,AGE, (char *)&ptlr[i]->age, 0) == -1) { (void)fprintf(stderr, "Failure to change AGE field -- %s\n", Fstrerror32(Ferror32)); (void)userlog("Clientfml failed to change AGE field -- %s\n", Fstrerror32(Ferror32)); (void)tpfree((char *)pF32); (void)tpfree((char *)pF32rec); (void)free(str1); for(i=0;i<3;i++){ (void)free(ptlr[i]); (void)free(ptlr2[i]); } (void)fclose(fp); (void)tpterm(); (void)exit(1); } if (Fadd32(pF32,PHONE, (char *)ptlr[i]->phone, 0) == -1) { (void)fprintf(stderr, "Failure to change PHONE field -- %s\n", Fstrerror32(Ferror32)); (void)userlog("Clientfml failed to change PHONE field -- %s\n", Fstrerror32(Ferror32)); (void)tpfree((char *)pF32); (void)tpfree((char *)pF32rec); (void)free(str1); for(i=0;i<3;i++){ (void)free(ptlr[i]); (void)free(ptlr2[i]); } (void)fclose(fp); (void)tpterm(); (void)exit(1); } } if (tpcall("FMLTEST", (char *)pF32, 0, (char **)&pF32rec, &len,0) == -1) { (void)fprintf(stderr, "Failure to call the FMLTEST service -- %s \n", tpstrerror(tperrno)); (void)userlog("Clientfml failed to call the FMLTEST service -- %s \n", tpstrerror(tperrno)); (void)tpfree((char *)pF32); (void)tpfree((char *)pF32rec); (void)free(str1); for(i=0;i<3;i++){ (void)free(ptlr[i]); (void)free(ptlr2[i]); } (void)fclose(fp); (void)tpterm(); (void)exit(1); } for(i=0;i<3;i++){ len2=10; if (Fget32(pF32rec,NAME, i, (char *)ptlr2[i]->name, &len2) == -1) { (void)fprintf(stderr, "Failure to call get the NAME field -- %s \n", Fstrerror32(Ferror32)); (void)userlog("Clientfml failed to get the NAME field -- %s \n", Fstrerror32(Ferror32)); (void)tpfree((char *)pF32); (void)tpfree((char *)pF32rec); (void)free(str1); for(i=0;i<3;i++){ (void)free(ptlr[i]); (void)free(ptlr2[i]); } (void)fclose(fp); (void)tpterm(); (void)exit(1); } len2=sizeof(long); if (Fget32(pF32rec,AGE, i, (char *)&ptlr2[i]->age, &len2) == -1) { (void)fprintf(stderr, "Failure to call get the AGE field -- %s \n", Fstrerror32(Ferror32)); (void)userlog("Clientfml failed to get the AGE field -- %s \n", Fstrerror32(Ferror32)); (void)tpfree((char *)pF32); (void)tpfree((char *)pF32rec); (void)free(str1); for(i=0;i<3;i++){ (void)free(ptlr[i]); (void)free(ptlr2[i]); } (void)fclose(fp); (void)tpterm(); (void)exit(1); } len2=12; if (Fget32(pF32rec,PHONE, i, (char *)ptlr2[i]->phone, &len2) == -1) { (void)fprintf(stderr, "Failure to call get the PHONE field -- %s \n", Fstrerror32(Ferror32)); (void)userlog("Clientfml failed to get the PHONE field -- %s \n", Fstrerror32(Ferror32)); (void)tpfree((char *)pF32); (void)tpfree((char *)pF32rec); (void)free(str1); for(i=0;i<3;i++){ (void)free(ptlr[i]); (void)free(ptlr2[i]); } (void)fclose(fp); (void)tpterm(); (void)exit(1); } len2=sizeof(long); if (Fget32(pF32rec,NO, i, (char *)&ptlr2[i]->no, &len2) == -1) { (void)fprintf(stderr, "Failure to call get the NO field -- %s \n", Fstrerror32(Ferror32)); (void)userlog("Clientfml failed to get the NO field -- %s \n", Fstrerror32(Ferror32)); (void)tpfree((char *)pF32); (void)tpfree((char *)pF32rec); (void)free(str1); for(i=0;i<3;i++){ (void)free(ptlr[i]); (void)free(ptlr2[i]); } (void)fclose(fp); (void)tpterm(); (void)exit(1); } (void)fprintf(stdout,"%s %ld %s %ld\n",ptlr2[i]->name,ptlr2[i]->age, ptlr2[i]->phone,ptlr2[i]->no); } (void)tpfree((char *)pF32); (void)tpfree((char *)pF32rec); (void)free(str1); for(i=0;i<3;i++){ (void)free(ptlr[i]); (void)free(ptlr2[i]); } (void)fclose(fp); (void)tpterm(); return(0); }编译客户端程序:
$buildclient -o clientfml -f clientfml.c
步骤五:
编写服务器端程序:
程序代码:
#include <stdio.h> #include "fml32.h" #include "atmi.h" #include "userlog.h" #include "fmlfile.h" void FMLTEST(TPSVCINFO *msg) { struct emp { char name[10]; long no; }; struct emp aa[3]={ {"hwt",33}, {"csq",21}, {"lht",42} }; struct emp bb[3]; FBFR32 *fP32; FLDLEN32 len2; float inputnum, result; int counter, numofocc,i,j; fP32 = (FBFR32 *)msg->data; if ((numofocc = Foccur32(fP32,NAME)) == -1) { (void)userlog("FMLserver failed to the number of NAME occurrences -- %s\n", Fstrerror32(Ferror32)); tpreturn(TPFAIL, 0, (char *)fP32, 0L, 0); } if (numofocc == 0) { (void)userlog("FMLserver received 0 NAME occurrences -- %s\n", Fstrerror32(Ferror32)); tpreturn(TPFAIL, 0, (char *)fP32, 0L, 0); } for (counter = 0; counter < numofocc; counter++) { len2 = sizeof(float); if (Fget32(fP32,NAME, counter, (char *)bb[counter].name, &len2) == -1) { (void)userlog("FMLserver failed to get NAME occ %d field -- %s\n", counter, Fstrerror32(Ferror32)); tpreturn(TPFAIL, 0, (char *)fP32, 0L, 0); } } for(i=0;i<3;i++) for(j=0;j<3;j++) { if(strcmp(bb[i].name,aa[j].name)==0){ if (Fchg32(fP32,NO,i, (char *)&aa[j].no, (FLDLEN32)0) == -1) { (void)userlog("FMLserver failed to add NO field -- %s\n", Fstrerror32(Ferror32)); tpreturn(TPFAIL, 0, (char *)fP32, 0L, 0); } } } tpreturn(TPSUCCESS, 0, (char *)fP32, 0L, 0); }编译服务器端程序:
$buildserver -o serverfml -f serverfml.c -s FMLTEST
步骤六:
启动服务:
[hwt@localhost fml]$ tmboot -y
Booting all admin and server processes in /home/hwt/fml/tuxconfig
INFO: BEA Tuxedo, Version 9.1, 32-bit, Patch Level (none)
INFO: Serial #: 454493271161-2664953090480, Expiration NONE, Maxusers 1000000
INFO: Licensed to: Customer
Booting admin processes ...
exec BBL -A :
process id=9898 ... Started.
Booting server processes ...
exec serverfml -A :
process id=9899 ... Started.
2 processes started.
检查一下:
[hwt@localhost fml]$ tmadmin
tmadmin - Copyright (c) 1996-1999 BEA Systems, Inc.
Portions * Copyright 1986-1997 RSA Data Security, Inc.
All Rights Reserved.
Distributed under license by BEA Systems, Inc.
Tuxedo is a registered trademark.
> psc
Service Name Routine Name Prog Name Grp Name ID Machine # Done Status
------------ ------------ --------- -------- -- ------- ------ ------
FMLTEST FMLTEST serverfml MATHG+ 1 SITE1 0 AVAIL
> psr
Prog Name Queue Name Grp Name ID RqDone Load Done Current Service
--------- ---------- -------- -- ------ --------- ---------------
BBL 155442 SITE1 0 0 0 ( IDLE )
serverfml 00001.00001 MATHGRP 1 0 0 ( IDLE )
步骤七:
执行客户端程序:
[hwt@localhost fml]$ ./clientfml tlr.txt
hwt 29 18677150924 33
lht 28 13398813422 42
csq 25 13234234564 21
小结:
本人本来C语言就不是很好,写这程序花了快2天,总结以下问题:
1.指针使用前要提前分配空间(malloc)
2.FML格式文件字段要大写
3.如果读取的是"|"分隔的文件,sscanf中应该用"%[^|]|%ld|%s"这样的格式
程序已经调试通过了,主要是练习FML的用法,希望能对大家学习有帮助。
[ 本帖最后由 khaz 于 2011-4-24 15:47 编辑 ]