Oracle Tuxedo工作站客户端与服务端的样例程序

服务端代码:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <ctype.h>
  5 #include <atmi.h>
  6 #include <userlog.h>
  7 
  8 static void trim(char *strIn, char *strOut){
  9    
 10    char *start, *end, *temp;
 11    
 12    temp = strIn;
 13    while (*temp == ' ')
 14    {
 15       ++temp;
 16    }
 17    
 18    start = temp; 
 19 
 20    temp = strIn + strlen(strIn) - 1; 
 21 
 22    while (*temp == ' '){
 23        --temp;
 24     }
 25  
 26    end = temp; 
 27    
 28    for (strIn = start; strIn <= end;){
 29         *strOut++ = *strIn++;     
 30    }
 31    
 32    *strOut = '';
 33     
 34 }
 35 
 36 // return 1 is true , 0 is false
 37 static int isDigit(const char* str, int len)
 38 {
 39     int i;
 40     if (len == 0)
 41     {
 42         return 0;
 43     }
 44     for (i = 0; i < len; ++i)
 45     {
 46         if (i == 0 && str[i] == '-') continue;
 47         
 48         if (!isdigit(str[i]))
 49         {
 50             return 0;
 51         }
 52     }
 53     return 1;
 54 }
 55 
 56 static int extractErrorCodeTagValue(const char* source)
 57 {
 58     char tagBeginStr[256] = { 0 };
 59     char tagEndStr[256] = { 0 };
 60     char errorCodeStr[256] = { 0 };
 61     char errorCodeStrOut[256] = { 0 };
 62     const char *beginPos = NULL;
 63     const char *endPos = NULL;
 64     const char* ERROR_CODE_TAG = "ERRORCODE";
 65 
 66     char *workPtr = NULL;
 67     int i = 0;
 68 
 69     if (source == NULL || strlen(source) == 0)
 70     {
 71         return -999;
 72     }
 73 
 74     sprintf(tagBeginStr, "<%s>", ERROR_CODE_TAG);
 75     sprintf(tagEndStr, "</%s>", ERROR_CODE_TAG);
 76 
 77     beginPos = strstr(source, tagBeginStr);
 78     endPos = strstr(source, tagEndStr);
 79 
 80     if (beginPos == NULL || endPos == NULL)
 81     {
 82         return -999;
 83     }
 84 
 85     for (workPtr = (char*)beginPos + strlen(tagBeginStr); workPtr != endPos; workPtr++,i++)
 86     {
 87         errorCodeStr[i] = *workPtr;
 88     }
 89 
 90     if (strlen(errorCodeStr) == 0)
 91     {
 92         return -999;
 93     }
 94 
 95     trim(errorCodeStr, errorCodeStrOut);
 96 
 97     if (!isDigit(errorCodeStrOut, strlen(errorCodeStrOut)))
 98     {
 99         return -999;
100     }
101     
102     return atoi(errorCodeStrOut);
103 
104 }
105 
106 
107 
108 EXEC SQL INCLUDE sqlca;
109 
110 EXEC SQL BEGIN DECLARE SECTION;
111 char result_out[3096] = "";
112 char* requestData = NULL;
113 long requestDataLen = 0;
114 char* resultData = NULL;
115 int retErrorCode = 0;
116 EXEC SQL VAR result_out IS STRING(3096);
117 EXEC SQL END DECLARE SECTION;
118 
119 TEST(TPSVCINFO *rqst)
120 
121 {
122 
123   requestData = rqst->data;
124   requestDataLen = rqst->len;
125   
126 
127   userlog("Request Data is:%s", requestData); 
128 
129   userlog("Request Data Length is:%d", requestDataLen);
130 
131   EXEC SQL EXECUTE  
132   DECLARE
133   result_out_sql varchar2(3096);
134   BEGIN
135     result_out_sql := ''; 
136     prc_K_testJsdQuery(:requestData,result_out_sql);
137     :result_out := result_out_sql;
138   END; 
139   END-EXEC;
140 
141 
142   userlog("result_out is: %s",result_out);
143 
144   retErrorCode = extractErrorCodeTagValue(result_out);
145   userlog("ret Error Code is: %d",retErrorCode);
146   if(retErrorCode != 0)
147   {
148     EXEC SQL ROLLBACK;
149     userlog("executed rollback");
150   }
151   else
152   {
153     EXEC SQL COMMIT;
154     userlog("executed commit");
155   }
156 
157   resultData = (char *)tpalloc("STRING",NULL,3096 + 1);
158   if(resultData)
159   {
160     memset(resultData,0,3096 + 1);
161     strncpy(resultData,result_out,3096);
162     userlog("result Data is: %s",resultData);
163     userlog("result Data Length is: %d",strlen(resultData));
164     tpreturn(TPSUCCESS,0,resultData,strlen(resultData),0);
165     tpfree(resultData);
166   }
167   else
168   {
169     tpreturn(TPFAIL,0,NULL,0,0);
170   }
171 
172 }

以上代码内嵌了SQL,采用了Oracle的Pro*C/C++ 编程方式,需要运行以下命令生成相应的可以编译的server_test.c文件:

proc USERID=[数据库账户名]/[数据库密码]@si2000 sqlcheck=SEMANTICS ireclen=512 iname=server_test.pc
 
然后再编译生成好的server_test.c文件:
buildserver -o server_test -f server_test.c -r Oracle_XA -s TEST
 
以上命令有个-s的参数是服务端代码里面Service Routine的名字,其实就是提供服务的函数名了。
 
因为Tuxedo是交易中间件,银行里面大量使用了这个。所以服务端的代码不可能不涉及分布式事务,所以需要运行以下命令行生成对应数据库的事务管理服务器(TMS):
buildtms -o TMS_ORA10G -r Oracle_XA
 
-o参数就是生成的TMS的exe文件名,这个文件的名称需要在TUXCONFIG文件中配置引用,这样启动的tuxedo服务才能使用事务。
 
然后配置TUXCONFIG文件,配置完成用tmloadcf命令生成加密后的二进制配置文件。
 
生成完成二进制配置文件之后暂时还不能启动Tuxedo服务,因为服务可能会使用事务。所以需要进入tmadmin命令中配置事务日志:
tmadmin
crdl -b [block_num] -z D:oracleproduct10.2.0db_2 uxedo12.1.3.0.0_VS2010samplesatmiconnect-database-testTLOG
crlog -m [master_node_name]
 
block_num一定要比TUXCONFIG文件中的TLOGSIZE大20-30%
master_node_name 其实就是TUXCONFIG文件中的MASTER 配置项的值,主节点的逻辑ID
 
以上命令都成功了以后,就可以使用tmboot命令启动Tuxedo服务了。服务端已经完美运行并连接数据库。下面来写客户端代码:
 
 1 /*功能:调用TUXEDO服务端的服务TEST,取EMPNO=1000所对应的ENAME的值,并显示出来*/
 2 #include <stdio.h>
 3 #include "atmi.h"
 4 main(argc,argv)
 5 {
 6     
 7 long reqlen=1024;
 8 char *sendbuf;
 9 char *rcvbuf;
10 
11 char *wsaddrEnv = tuxgetenv("WSNADDR");
12 if(wsaddrEnv)
13 {
14     fprintf(stderr,"wsnaddr is:%s
",wsaddrEnv);
15 }
16 /* 与TUXEDO服务端建立连接 */
17 if (tpinit((TPINIT *) NULL) == -1)
18 {
19 (void) fprintf(stderr,"Tpinit failedn");
20 exit(1);
21 }
22 
23 /* 分配发送缓冲区*/
24 
25 sendbuf = (char *)tpalloc("STRING",NULL,reqlen);
26 
27 if ( sendbuf == (char *)NULL)
28 
29 {
30 
31 printf("tpalloc failedn");
32 
33 tpterm();
34 
35 }
36 
37 /* 分配接受缓冲区*/
38 rcvbuf = (char *)tpalloc("STRING",NULL,reqlen);
39 
40 if ( rcvbuf == (char *)NULL)
41 
42 {
43 
44 printf("tpalloc failedn");
45 
46 tpterm();
47 
48 }
49 
50 strcpy(sendbuf,"<AKC190>L2017262210000651420</AKC190><YYBM>0080</YYBM>");
51 
52 /*调用TUXEDO的服务TEST*/
53 
54 if (tpcall("TEST", (char *)sendbuf, 0L, (char **)&rcvbuf, (long *)&reqlen, 0<  0 ) )
55 /*tpcall("TOUPPER", (char *)sendbuf, 0, (char **)&rcvbuf, &rcvlen, (long)0))*/
56 {
57     
58 printf("tpcall failed,tperrno=%ld,tperrtext=%s
",tperrno,tpstrerror(tperrno)); 
59   
60 tpfree(rcvbuf); 
61   
62 tpterm();  
63  
64 exit(1);
65 
66 }
67 
68 printf("name=%s
",rcvbuf);
69 
70 tpfree(rcvbuf);
71 
72 tpfree(sendbuf);
73 
74 tpterm();
75 
76 return(0);
77 
78 }

然后以上代码用以下命令行来编译:

buildclient -o client_test -f client_test.c -w
 
-w参数必须加上,因为是远程客户端连接Tuxedo服务(客户端和服务端不在一台物理机上),如果是本地客户端连接Tuxedo服务(客户端和服务端在一台物理机上),就不用加-w
 
 
references:
http://blog.163.com/lover_j_j/blog/static/1682474472007101591059797/
https://docs.oracle.com/cd/B14117_01/appdev.101/a97269/pc_01int.htm#sthref50
https://docs.oracle.com/en/database/oracle/oracle-database/12.2/adfns/xa.html#GUID-22284B0A-C63F-471A-96ED-AEA195068944
https://wenku.baidu.com/view/ef4b38c5580216fc710afdcf.html
http://blog.csdn.net/cemer815/article/details/5493081
http://stevenos.iteye.com/blog/362630
原文地址:https://www.cnblogs.com/foohack/p/8534187.html