服务端代码:

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <atmi.h>
#include <userlog.h> static void trim(char *strIn, char *strOut){ char *start, *end, *temp; temp = strIn;
while (*temp == ' ')
{
++temp;
} start = temp; temp = strIn + strlen(strIn) - ; while (*temp == ' '){
--temp;
} end = temp; for (strIn = start; strIn <= end;){
*strOut++ = *strIn++;
} *strOut = '\0'; } // return 1 is true , 0 is false
static int isDigit(const char* str, int len)
{
int i;
if (len == )
{
return ;
}
for (i = ; i < len; ++i)
{
if (i == && str[i] == '-') continue; if (!isdigit(str[i]))
{
return ;
}
}
return ;
} static int extractErrorCodeTagValue(const char* source)
{
char tagBeginStr[] = { };
char tagEndStr[] = { };
char errorCodeStr[] = { };
char errorCodeStrOut[] = { };
const char *beginPos = NULL;
const char *endPos = NULL;
const char* ERROR_CODE_TAG = "ERRORCODE"; char *workPtr = NULL;
int i = ; if (source == NULL || strlen(source) == )
{
return -;
} sprintf(tagBeginStr, "<%s>", ERROR_CODE_TAG);
sprintf(tagEndStr, "</%s>", ERROR_CODE_TAG); beginPos = strstr(source, tagBeginStr);
endPos = strstr(source, tagEndStr); if (beginPos == NULL || endPos == NULL)
{
return -;
} for (workPtr = (char*)beginPos + strlen(tagBeginStr); workPtr != endPos; workPtr++,i++)
{
errorCodeStr[i] = *workPtr;
} if (strlen(errorCodeStr) == )
{
return -;
} trim(errorCodeStr, errorCodeStrOut); if (!isDigit(errorCodeStrOut, strlen(errorCodeStrOut)))
{
return -;
} return atoi(errorCodeStrOut); } EXEC SQL INCLUDE sqlca; EXEC SQL BEGIN DECLARE SECTION;
char result_out[] = "";
char* requestData = NULL;
long requestDataLen = ;
char* resultData = NULL;
int retErrorCode = ;
EXEC SQL VAR result_out IS STRING();
EXEC SQL END DECLARE SECTION; TEST(TPSVCINFO *rqst) { requestData = rqst->data;
requestDataLen = rqst->len; userlog("Request Data is:%s", requestData); userlog("Request Data Length is:%d", requestDataLen); EXEC SQL EXECUTE
DECLARE
result_out_sql varchar2();
BEGIN
result_out_sql := '';
prc_K_testJsdQuery(:requestData,result_out_sql);
:result_out := result_out_sql;
END;
END-EXEC; userlog("result_out is: %s",result_out); retErrorCode = extractErrorCodeTagValue(result_out);
userlog("ret Error Code is: %d",retErrorCode);
if(retErrorCode != )
{
EXEC SQL ROLLBACK;
userlog("executed rollback");
}
else
{
EXEC SQL COMMIT;
userlog("executed commit");
} resultData = (char *)tpalloc("STRING",NULL, + );
if(resultData)
{
memset(resultData,, + );
strncpy(resultData,result_out,);
userlog("result Data is: %s",resultData);
userlog("result Data Length is: %d",strlen(resultData));
tpreturn(TPSUCCESS,,resultData,strlen(resultData),);
tpfree(resultData);
}
else
{
tpreturn(TPFAIL,,NULL,,);
} }

以上代码内嵌了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:\oracle\product\10.2.0\db_2\tuxedo12.1.3.0.0_VS2010\samples\atmi\connect-database-test\TLOG
crlog -m [master_node_name]
 
block_num一定要比TUXCONFIG文件中的TLOGSIZE大20-30%
master_node_name 其实就是TUXCONFIG文件中的MASTER 配置项的值,主节点的逻辑ID
 
以上命令都成功了以后,就可以使用tmboot命令启动Tuxedo服务了。服务端已经完美运行并连接数据库。下面来写客户端代码:
 
 /*功能:调用TUXEDO服务端的服务TEST,取EMPNO=1000所对应的ENAME的值,并显示出来*/
#include <stdio.h>
#include "atmi.h"
main(argc,argv)
{ long reqlen=;
char *sendbuf;
char *rcvbuf; char *wsaddrEnv = tuxgetenv("WSNADDR");
if(wsaddrEnv)
{
fprintf(stderr,"wsnaddr is:%s\n",wsaddrEnv);
}
/* 与TUXEDO服务端建立连接 */
if (tpinit((TPINIT *) NULL) == -)
{
(void) fprintf(stderr,"Tpinit failedn");
exit();
} /* 分配发送缓冲区*/ sendbuf = (char *)tpalloc("STRING",NULL,reqlen); if ( sendbuf == (char *)NULL) { printf("tpalloc failedn"); tpterm(); } /* 分配接受缓冲区*/
rcvbuf = (char *)tpalloc("STRING",NULL,reqlen); if ( rcvbuf == (char *)NULL) { printf("tpalloc failedn"); tpterm(); } strcpy(sendbuf,"<AKC190>L2017262210000651420</AKC190><YYBM>0080</YYBM>"); /*调用TUXEDO的服务TEST*/ if (tpcall("TEST", (char *)sendbuf, 0L, (char **)&rcvbuf, (long *)&reqlen, < ) )
/*tpcall("TOUPPER", (char *)sendbuf, 0, (char **)&rcvbuf, &rcvlen, (long)0))*/
{ printf("tpcall failed,tperrno=%ld,tperrtext=%s\n",tperrno,tpstrerror(tperrno)); tpfree(rcvbuf); tpterm(); exit(); } printf("name=%s\n",rcvbuf); tpfree(rcvbuf); tpfree(sendbuf); tpterm(); return(); }

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

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

Oracle Tuxedo工作站客户端与服务端的样例程序的更多相关文章

  1. Tuxedo安装、配置、以及演示样例程序 (学习网址)

    Tuxedo安装.配置.以及演示样例程序 (学习网址): 1.http://liu9403.iteye.com/blog/1415684 2.http://www.cnblogs.com/fnng/a ...

  2. aiohttp web服务端(server)样例 (非client)

    python版本 python3.6 (其他版本需要小改,版本>python3.4) 参考网址:https://www.cnblogs.com/ameile/p/5589808.html  as ...

  3. 同一台电脑同时装Oracle客户端和服务端

    1.如果之前安装过Oracle,Win+R输入Services.msc,关掉以Oracle开头的服务(卸载Oracle服务端和客户端步骤一样,见另外一篇帖子) 2.Win+R输入regedit打开注册 ...

  4. 安装_oracle11G_客户端_服务端_链接_oracle

    在开始之前呢,有一些注细节需要注意,oracle11G_客户端_和_服务端, 分为两种   一种是  开发者使用    一种是  BDA  自己使用(同时也需要根据自己 PC 的系统来做_win7_与 ...

  5. TCP学习之五:客户端、服务端异步传输字符串

    参考学习张子阳大神的博客:http://www.cnblogs.com/JimmyZhang/category/101698.html 消息发送接口: 消息接收接口: 客户端: 服务端: 消息发送类: ...

  6. TCP学习之三:客户端、服务端同步传输字符串

    参考学习张子阳大神的博客:http://www.cnblogs.com/JimmyZhang/category/101698.html 一个客户端.发送一条消息 客户端: 服务端: 注意:Networ ...

  7. 客户端向服务端传送特殊字符解决方法(检测到有潜在危险的 Request.Form 值)

    当客户端向服务端传输特殊字符时报错,错误信息如下图:

  8. [Java]Hessian客户端和服务端代码例子

    简要说明:这是一个比较简单的hessian客户端和服务端,主要实现从客户端发送指定的数据量到服务端,然后服务端在将接收到的数据原封不动返回到客户端.设计该hessian客户端和服务端的初衷是为了做一个 ...

  9. SignalR 实现web浏览器客户端与服务端的推送功能

    SignalR 是一个集成的客户端与服务器库,基于浏览器的客户端和基于 ASP.NET 的服务器组件可以借助它来进行双向多步对话. 换句话说,该对话可不受限制地进行单个无状态请求/响应数据交换:它将继 ...

随机推荐

  1. JavaScript:Date 对象

    ylbtech-JavaScript:Date 对象 1.返回顶部 Date 对象 Date 对象用于处理日期和时间. 创建 Date 对象的语法: var myDate=new Date() 注释: ...

  2. 接收连接basic_socket_acceptor

    概述 TCP有一处和UDP不同的地方是TCP是面向连接的,TCP有建立连接.通信.关闭连接的操作,Boost.Asio提供了ip::tcp::acceptor用来接收新的TCP连接,底层由socket ...

  3. Nuget挂了的解决方法(转)

    今天用Nuget下一个程序包时,发现Nuget挂了:未能解析此远程名称:'nuget.org'.第一反应就是方校长抖威风了,挂个代理上 http://nuget.org 试了下,果然好好的. 用命令n ...

  4. qt文字改变方向

    QPainter painter(this);             QFont font("Courier", 24);             painter.setFont ...

  5. 文本分类需要CNN?No!fastText完美解决你的需求(后篇)

    http://blog.csdn.net/weixin_36604953/article/details/78324834 想必通过前一篇的介绍,各位小主已经对word2vec以及CBOW和Skip- ...

  6. Spring(二十一):Spring JdbcTemplate、NamedParameterJdbcTemplate具名参数

    JdbcTemplate主要提供以下五类方法: execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句: update方法及batchUpdate方法:update方法用于执行新增.修 ...

  7. O2O、C2C、B2B、B2C

    一.O2O.C2C.B2B.B2C的区别在哪里? O2O是Online to offline 分为四种运营模式 1.Online to offline 是线上交易到线下消费体验 2.Offline t ...

  8. Android 开源项目 eoe 社区 Android 客户端

    本文内容 环境 开源项目 eoe 社区 Android 客户端 本文介绍 eoe 社区 Android 客户端.它是一个开源项目,功能相对简单,采用侧边菜单栏.可以学习一下.点击此处查看 GitHub ...

  9. springboot项目启动多个实例的方法

    我现在需要实现这样的功能:将一个服务提供者启动多个实例,下面我列出在eclipse中启动多个实例的方法: 首先看一下我的服务提供者的项目文件结构: springboot默认的配置文件是applicat ...

  10. iOS9 Error Domain=NSURLErrorDomain Code=-1022 App Transport Security (ATS)

    iOS 9在HTTP 访问时会出错  iOS9 Error Domain=NSURLErrorDomain Code=-1022 这时需要修改info.plist 文件 在Info.plist中添加N ...