第八章TUXEDO的通讯方式.docx

上传人:b****8 文档编号:11108548 上传时间:2023-02-25 格式:DOCX 页数:54 大小:102.55KB
下载 相关 举报
第八章TUXEDO的通讯方式.docx_第1页
第1页 / 共54页
第八章TUXEDO的通讯方式.docx_第2页
第2页 / 共54页
第八章TUXEDO的通讯方式.docx_第3页
第3页 / 共54页
第八章TUXEDO的通讯方式.docx_第4页
第4页 / 共54页
第八章TUXEDO的通讯方式.docx_第5页
第5页 / 共54页
点击查看更多>>
下载资源
资源描述

第八章TUXEDO的通讯方式.docx

《第八章TUXEDO的通讯方式.docx》由会员分享,可在线阅读,更多相关《第八章TUXEDO的通讯方式.docx(54页珍藏版)》请在冰豆网上搜索。

第八章TUXEDO的通讯方式.docx

第八章TUXEDO的通讯方式

第八章:

TUXEDO的通讯方式

TUXEDO中的客户端与服务端之间可以采用的通讯方式有:

1.同步调用方式

2.异步调用方式

3.管道方式

4.会话方式

5.消息方式

6.事件发布订阅方式

7./Q方式

注意:

1.服务端的SERVICE之间,可以采用管道方式,客户端与服务端之间不能采用。

2.客户端与服务端之间可以采用消息方式,服务端的SERVICE之间不能采用消息方式。

3.其他通讯方式在服务端的SERVICE之间,及客户端与服务端之间都可以采用。

管道方式(tpforward())在服务端编程中有说明,/Q方式在第十章中在介绍,对这两种方式在本章种不做介绍.

8.1同步调用方式

如下图所示:

在同步请求/回答方式中,客户端使用tpcall()给本地或远程的服务器(由TUXEDO系统根据公告板信息确定)发送服务请求,此时客户将传送请求服务的名字、用于请求服务的输入参数和输出参数,tpcall()发出后,客户的数据被传送至服务器,得到相应的服务处理。

在此方式下,服务器处理请求时,客户端将等待,不继续运行,直到服务器返回相应结果。

调用过程如图:

 

例子:

客户端通过对一个文件分块,每调用一次TPCALL()发送一块数据,把一个文件从客户端传送到服务端。

客户端与服务端采用FML32缓冲区进行通信。

在异步调用方式和会话方式中也用到该例子。

可以做一个比较。

在该例子中我们把块的大小定义为

1024字节。

采用FML32缓冲区。

FML32定义文件Myfml.h的内容:

*base100

#namenumbertypeflagscomments

FNAME1string--

BNUM3long

BID4long--

FDATA5carray--

BSIZE6long--

 

服务端程序Call.c的内容:

#include

#include

#include

#include

#include"fml32.h"

#include"myfml.h"

 

CALL(TPSVCINFO*rqst)

{

FILE*fp;

longi=0;

FBFR32*rcvbuf;

charfname[100]="";

FLDLEN32len=0;

longbid=0;

longbsize=1024;/*传送的块大小为1024字节*/

char*fdata;

rcvbuf=(FBFR32*)rqst->data;

len=sizeof(bid);

if(Fget32(rcvbuf,BID,0,(char*)&bid,&len)==-1)

{

userlog("Fget32(BID)failure:

%s",(char*)Fstrerror32(Ferror32));

tpreturn(TPFAIL,0,0,0,0);

}

len=sizeof(fname);

if(Fget32(rcvbuf,FNAME,0,fname,&len)==-1)

{

userlog("Fget32(FNAME)failure:

%s",(char*)Fstrerror32(Ferror32));

tpreturn(TPFAIL,0,0,0,0);

}

strcat(fname,".s");

if((fp=fopen(fname,"rb"))==NULL)

{

fp=fopen(fname,"wb");

}

elseif(bid==0)

{

fclose(fp);

fp=fopen(fname,"wb");

}

else

{

fclose(fp);

fp=fopen(fname,"r+b");

}

if(fp==NULL)

{

userlog("fopen()%sfailure\n",fname);

tpreturn(TPFAIL,0,0,0,0);

}

fdata=(char*)malloc(bsize+1);

if(fdata==NULL)

{

userlog("malloc(fdata)failure");

tpreturn(TPFAIL,0,0,0,0);

}

len=bsize;

if(Fget32(rcvbuf,FDATA,0,fdata,(FLDLEN32*)&len)==-1)

{

userlog("Fget32(FDATA)failure:

%s",(char*)Fstrerror32(Ferror32));

tpreturn(TPFAIL,0,0,0,0);

}

i=bid*bsize;

if(fseek(fp,i,0)!

=0)

{

userlog("fseek()failure\n");

tpreturn(TPFAIL,0,0,0,0);

}

i=fwrite(fdata,1,len,fp);

if(i!

=len)

{

userlog("fwrite()fail\n");

tpreturn(TPFAIL,0,0,0,0);

}

fclose(fp);

tpreturn(TPSUCCESS,0,NULL,0L,0);

}

 

客户端程序callcli.c的内容:

#include

#include

#include"atmi.h"

#include"fml32.h"

#include"myfml.h"

 

FBFR32*sendbuf=NULL;

char*filebuf;

FILE*fp;

 

log(constchar*fmt,...)

{

va_listap;

va_start(ap,fmt);

vfprintf(stdout,fmt,ap);

fflush(stdout);

va_end(ap);

fclose(fp);

tpfree((char*)sendbuf);

free(filebuf);

tpterm();

exit

(1);

}

 

main(intargc,char*argv[])

{

longrcvlen=0;

longfilelen=0;

longi=0;

intret=0;

longreallen=0;

longbnum=0;

longbsize=1024;/*传送的块大小为1024字节*/

FLDLEN32len=0;

if(argc!

=2)

{

(void)fprintf(stderr,"Usage:

%sfilename\n",argv[0]);

exit

(1);

}

fp=fopen(argv[1],"rb");

if(fp==NULL)

{

printf("openfile:

%sfailure\n",argv[1]);

exit

(1);

}

if(fseek(fp,0,SEEK_END)!

=0)

{

perror("fseek()failure:

");

exit

(1);

}

filelen=ftell(fp);

if(filelen==-1)

{

perror("ftell()failure:

");

exit

(1);

}

rewind(fp);

if((sendbuf=(FBFR32*)tpalloc("FML32",NULL,bsize+1024))==(FBFR32*)NULL)

{

printf("Errorallocatingsendbuffer\n");

exit

(1);

}

len=Fsizeof32(sendbuf);

if(Finit32(sendbuf,(FLDLEN32)len)==-1)

{

printf("finit32()failure\n");

exit

(1);

}

if(tpinit(NULL)==-1)

{

printf("tpinit()failure");

exit

(1);

}

filebuf=(char*)malloc(bsize);

if(filebuf==NULL)

{

printf("malloc(filebuf)failure");

exit

(1);

}

bnum=(filelen-1)/bsize+1;

if(Fchg32(sendbuf,FNAME,0,argv[1],(FLDLEN32)len)<0)

{

log("Fchg32(FNAME)failure\n",Fstrerror32(Ferror32));

}

printf("filelen=%ld,blocknum=%ld\n",filelen,bnum);

for(i=0;i

{

if(fseek(fp,i*bsize,0)!

=0)

{

log("fseekfailure\n");

}

reallen=fread(filebuf,1,bsize,fp);

if(reallen!

=bsize&&feof(fp)==0)

{

log("fread()failure\n");

}

if(Fchg32(sendbuf,BID,0,(char*)&i,0)<0)

{

log("Fchg32(BID)failure:

%s\n",Fstrerror32(Ferror32));

}

printf("bid=%ld\n",i);

if(Fchg32(sendbuf,FDATA,0,filebuf,(FLDLEN32)reallen)<0)

{

log("Fchg32(FDATA)failure:

%s\n",Fstrerror32(Ferror32));

}

ret=tpcall("CALL",(char*)sendbuf,0,(char**)&sendbuf,&rcvlen,(long)0);

if(ret==-1)

{

log("tpcall()failure:

tperrno=%ld,errstr=%s\n",tperrno,tpstrerror(tperrno));

}

}

log("finished\n");

}

 

8.2异步调用方式

如图所示:

在异步请求/回答方式中,客户端使用tpacall()给本地或远程的服务器(由TUXEDO系统根据公告板信息确定)发送服务请求,与同步方式不同的是:

在此方式下,服务器处理请求时,客户端继续运行。

当客户端想得到请求的处理结果时,用tpgetrply()将结果取回。

调用过程如图:

 

 

例子:

该例子实现与同步调用方式一样的功能.但在该例子中采用异步通讯方式.

服务端的程序与同步调用方式中的一样,客户端的程序Acallcli.c的内容如下:

注意:

每调用TPACALL()50次之后,就要调用tpgetrply()把服务端返回的结果取出,

否则,返回缓冲区会满,会出如下错误:

atpcall()failure:

tperrno=5,errstr=TPELIMIT-asystemlimithasbeenreached

Acallcli.c的内容:

#include

#include

#include"atmi.h"

#include"fml32.h"

#include"myfml.h"

 

FBFR32*sendbuf=NULL;

char*filebuf;

FILE*fp;

 

log(constchar*fmt,...)

{

va_listap;

va_start(ap,fmt);

vfprintf(stdout,fmt,ap);

fflush(stdout);

va_end(ap);

fclose(fp);

tpfree((char*)sendbuf);

free(filebuf);

tpterm();

exit

(1);

}

 

main(intargc,char*argv[])

{

longrcvlen=0;

longfilelen=0;

longi=0;

intret=0;

longreallen=0;

longbnum=0;

longbsize=1024;/*传送的块大小为1024字节*/

FLDLEN32len=0;

longj=0;

intcd[50];

if(argc!

=2)

{

(void)fprintf(stderr,"Usage:

%sfilename\n",argv[0]);

exit

(1);

}

fp=fopen(argv[1],"rb");

if(fp==NULL)

{

printf("openfile:

%sfailure\n",argv[1]);

exit

(1);

}

if(fseek(fp,0,SEEK_END)!

=0)

{

perror("fseek()failure:

");

exit

(1);

}

filelen=ftell(fp);

rewind(fp);

if((sendbuf=(FBFR32*)tpalloc("FML32",NULL,bsize+1024))==(FBFR32*)NULL)

{

printf("Errorallocatingsendbuffer\n");

exit

(1);

}

len=Fsizeof32(sendbuf);

if(Finit32(sendbuf,(FLDLEN32)len)==-1)

{

printf("finit32()failure\n");

exit

(1);

}

if(tpinit(NULL)==-1)

{

printf("tpinit()failure");

exit

(1);

}

filebuf=(char*)malloc(bsize);

if(filebuf==NULL)

{

printf("malloc(filebuf)failure");

exit

(1);

}

bnum=(filelen-1)/bsize+1;

if(Fchg32(sendbuf,FNAME,0,argv[1],(FLDLEN32)len)<0)

{

log("Fchg32(FNAME)failure\n",Fstrerror32(Ferror32));

}

printf("filelen=%ld,blocknum=%ld\n",filelen,bnum);

j=0;

for(i=0;i

{

if(fseek(fp,i*bsize,0)!

=0)

{

log("fseekfailure\n");

}

reallen=fread(filebuf,1,bsize,fp);

if(reallen!

=bsize&&feof(fp)==0)

{

log("fread()failure\n");

}

if(Fchg32(sendbuf,BID,0,(char*)&i,0)<0)

{

log("Fchg32(BID)failure:

%s\n",Fstrerror32(Ferror32));

}

printf("bid=%ld\n",i);

if(Fchg32(sendbuf,FDATA,0,filebuf,(FLDLEN32)reallen)<0)

{

log("Fchg32(FDATA)failure:

%s\n",Fstrerror32(Ferror32));

}

ret=tpacall("CALL",(char*)sendbuf,0,0);

if(ret==-1)

{

log("atpcall()failure:

tperrno=%ld,errstr=%s\n",tperrno,tpstrerror(tperrno));

}

cd[j]=ret;

j++;

if(j%50==0)

{

for(j=0;j<50;j++)

{

if(tpgetrply(&cd[j],(char**)&sendbuf,&rcvlen,(long)0)==-1)

{

log("tpgetrply()failure:

cd=%ld,errstr=%s\n",cd,tpstrerror(tperrno));

}

}

j=0;

}

}

log("finished\n");

}

 

8.3会话方式

采用会话通讯方式,通讯双方在建立连接之后,可以多次发送或接收数据,TUXEDO中采用的是半双工的通讯方式,这种方式特别适用于大批量的数据传输。

名称解释:

发起者(originator,initiator):

发起该会话的进程,它调用tpconnect()与服务端的一个SERVICE建立连接

从属者(subordinate):

tpconnect()中指定的SERVICE

发送者(sender):

当前拥有发送权的进程,它只能发送数据

接收者(receiver):

当前拥有发送权的进程,它只能接收数据

 

函数说明:

inttpconnect(char*name,char*data,longlength,longflags)

描述:

与名为name的SERVICE建立连接

参数:

name:

SERVICE的名字

*data:

要发送的数据

length:

数据的长度

flags:

可以为TPNOTRAN,TPNOTIME,TPNOBLOCK,TPSIGRSTRT

TPSENDONLY:

发送者只能发送数据,被调用的SERVICE只能接收数据

TPRECVONLY:

发送者只能接收数据,被调用的SERVICE只能发送数据

返回值:

成功返回一个标识该连接的标识符,失败为-1

 

inttpsend(intcd,char*data,longlength,longflags,long*revent)

描述:

用于发送数据

参数:

cd:

tpconnect()的返回值,用于标识该连接

data:

要发送的数据

length:

要发送的数据的长度

flags:

(TPNOBLOCK,TPNOTIME,TPSIGRSTRT

TPRECVONLY:

把发送权交给接受者,在接受者那里会产生事件TPEV_SENDONLY。

revent:

当返回值为-1时,如果tperrno=TPEEVENT,那么表明有事件发生。

可能的事件有:

TPEV_DISCONIMM:

当会话的发起者调用tpdiscon(),tpreturn(),tpcommit()时,会话的

从属者会收到该事件。

如果有网络故障等,那么会话的发起者也会收到该

事件。

TPEV_SVCFAIL:

会话的发起者会收到该事件,表明会话的从属者调用tpreturn(TPFAIL)

或tpreturn(TPEXIT),并且该会话的从属者不在拥有该控制权

TPEV_SVCERR:

会话的发起者会收到该事件,表明会话的从属者调用

tpreturn(TPSUCCESS,..)返回,并且该会话的从属者不在拥有该控制权.

返回值:

失败为-1,如果tperrno=TPEEVENT,那么导致该调用失败的事件保存在revent中

 

inttprecv(intcd,char**data,long*length,longflags,long*revent)

描述:

用于接收数据

data:

接收的数据放到该缓冲区中

length:

接收大的数据的长度

flags:

(TPNOCHANGE,TPNOBLOCK,TPNOTIME,TPSIGRSTRT)

revent:

当返回值为-1时,如果tperrno=TPEEVENT,那么表明有事件发生。

可能的事件有:

TPEV_DISCONIMM:

与tpsend()中的含义一样.

TPRECVONLY:

该会话的发送者把发送权交给接受者,在接受者这里会产生事TPEV_SENDONLY。

TPEV_SVCFAIL:

与tpsend()中的含义一样.

TPEV_SVCERR:

与tpsend()中的含义一样.

TPEV_SVCSUCC:

该会话的从属者已成功完成并关闭该会话,那么会话的发起者会收到该事件.表明该会话已成功结束.

返回值:

失败为-1,如果tperrno=TPEEVENT,那么导致该调用失败的事件保存在revent中

 

inttpdiscon(intcd)

描述:

关闭标识符为cd的会话

参数:

tpconnect()的返回值,用于标识该连接

返回值:

失败为-1

 

会话通讯方式的整个过程如图所示:

 

例子:

该例子实现与同步通讯的例子一样的功能,但采用的是会话通讯方式.

服务端程序的内容:

#include

#include

#include

#include"fml32.h"

#include"myfml.h"

longbsize=1024;/*传送的块大小为1024字节*/

FBFR32*rcvbuf;

charfname[256]="";

char*fdata;

 

tpsvrinit(intargc,char**argv)

{

if((rcvbuf=(FBFR32*)tpalloc("FML32",NULL,(bsize+1024)))==NULL)

{

userlog("tpallocfai

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 经济学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1