会话ATMII
索引:
1.概念
会话是一个半双工的链路,同一时刻只有一方能发送,另一方只能接收。
会话的client方开始时也要调用tpinit()加入到tuxedo应用中,通讯使用的缓冲区也要用tpalloc()分配。
在会话中有如下几个角色:
- originator, initiator:执行tpconnect开始会话的一方;
- subordinate:接收tpconnect的会话server;
- sender:控制着会话连接的一方;
- receiver:没有会话连接控制权的一方。
2.tpconnect
建立与会话service的连接。
int tpconnect(char* name, char *data, long length, long flags);
参数说明:
name:会话service的名称;
data:发送数据的buffer,可以是NULL;
length:buffer的长度(必要的话);
flags:标志。有如下值:
- TPNOTRAN:与tpacall介绍的相同;
- TPNOBLOCK:(同上);
- TPNOTIME:(同上);
- TPSIGRSTRT:(同上);
- TPSENDONLY:对建立的连接具有控制权,initiator将发送数据,被调用方只能接收数据;
- TPRECVONLY:建立连接后把控制权交给被调用方,initiator只能接收数据;
TPSENDONLY和TPRECVONLY必须指定一个,以决定会话的控制权和方向,之后控制权和方向的改变由sender决定。
成功返回一个非负的连接描述符,供后面的tpsend()、tprecv()和tpdiscon()使用。失败返回-1。
失败原因:
- 无效的参数;
- 太多的连接要建立。每个进程允许建立10条连接;
- 错误的service名或非会话service。
3.tpsend
在一个会话连接中发送消息。
int tpsend(int cd, char *data, long length, long flags, long *revent);
参数说明:
cd:会话连接描述符(tpconnect返回值);
data:发送的数据指针。可以为NULL,如交换控制权;
length:发送数据的长度(必要的话);
flags:标志。
- TPNOBLOCK:同tpacall;
- TPNOTIME:(同上);
- TPSIGRSTRT:(同上);
- TPRECVONLY:在发送数据之后,放弃连接的控制权;这将导致对方收到TPEV_SENDONLY事件;
revent:当tperrno为TPEEVENT时返回的事件值。
失败时函数返回-1,tperrno被设置。当tperrno为TPEEVENT时,导致失败的具体事件存放在revent中。
调用tpsend()可能出现的revent值有:
- TPEV_DISCONIMM:当会话的originator执行tpdiscon()、tpreturn()、tpcommit()时subordinate会收到该事件;当进程或网络错误时originator也会收到此事件;
- TPEV_SVCFAIL:当subordinate没有会话的控制权而使用TPFAIL和TPEXIT执行tpreturn时originator将收到该事件;
- TPEV_SVCERR:当subordinate没有会话的控制权而使用TPSUCCESS执行tpreturn时originator将收到该事件;
4.tprecv
没有会话控制权的一方执行接收消息。
int tprecv(int cd, char **data, long *length, long flags, long *revent);
参数说明:
cd:会话连接描述符;
data:接收buffer的地址的地址;
length:接收数据的长度的地址;
flags:标志。可选值:
- TPNOCHANGE:参见tpacall();
- TPNOBLOCK:同上;
- TPNOTIME:同上;
- TPSIGRSTRT:同上;
revent:当tperrno为TPEEVENT时返回的事件值。
失败时函数返回-1,tperrno被设置。当tperrno为TPEEVENT时,导致失败的具体事件存放在revent中。
调用tprecv()可能出现的revent值有:
- TPEV_DISCONIMM:当会话的originator执行tpdiscon()、tpreturn()、tpcommit()时subordinate会收到该事件;当进程或网络错误时originator也会收到此事件;
- TPEV_SENDONLY:发送方已经放弃了控制权,调用进程当前只能发送不能接收。也可用此方法获得调用者当前处于的模式;
- TPEV_SVCFAIL:当subordinate没有会话的控制权而使用TPFAIL和TPEXIT执行tpreturn时originator将收到该事件;
- TPEV_SVCERR:当subordinate没有会话的控制权而使用TPSUCCESS执行tpreturn时originator将收到该事件;
- TPEV_SVCSUCC:subordinate成功结束并正在关闭连接(必须是会话的最后一个事件)。
使用举例:
for (;;) { (void)gets(reply); if (strcmp(reply, “q”) == 0 ) break; (void) strcpy(line, reply); /* send balance request and relinquish line control.*/ if (tpsend(cd,line,0,TPRECVONLY,&revent) == -1) { (void)tpterm(); exit(1); } /* wait for service to return balance request results.*/ if (tprecv(cd, &line, &len,TPNOCHANGE, &revent) != -1) { (void) userlog(“TPEV_SENDONLY event expected”); (void)tpterm(); exit(1); } /*anything other than a send event is an error.*/ if ((tperrno != TPEEVENT) || \ (tperrno == TPEEVENT && revent != TPEV_SENDONLY)) { (void)tpterm(); exit(1); } (void) printf(Another request ?? %s\n ”,line); }
5.tpdiscon
该函数只能由会话的建立方originator执行,这导致会话非正常的终止。
int tpdiscon(int cd);
参数说明:
cd:会话连接描述符。
该函数执行后将导致对方收到一个TPEV_DISCONIMM事件。这种方法可能会丢失数据,关闭会话连接的好的方法是由service执行tpreturn。
失败返回-1。出错原因可能有:TPEBADDESC、TPETIME。
6.会话server正常返回的流程示例
- client执行tpconnect(),使用标志TPSENDONLY,控制连接;
- client使用标志TPRECVONLY调用tpsend(),把控制权交个对方,在server端产生TPEV_SENDONLY事件;
- server执行tpreturn(),标志TPSUCCESS,中断连接,给client产生一个TEEV_SVCSUCC事件;
- client调用tprecv(),获得该事件,得知连接已经关闭。
7.会话server不正常返回流程示例
- client执行tpconnect(),使用标志TPSENDONLY,控制连接;
- client不使用标志调用tpsend(),控制权仍在client端;
- server使用tprecv()得知自己不能send数据;
- server发生错误,在没有控制权的情况下执行tpreturn(),使用标志TPFAIL,给client产生TPEV_SVCERR;
- 当client调用tpsend()时得到这个事件。