본문 바로가기

UNIX_LINUX_C_C++

[TMAX] 비요청 메세지를 보내기

출처 : http://honor.pe.kr/tt/board/ttboard.cgi?act=read&db=tiptech&page=1&idx=118

비요청 메세지를 보내기 위해 여기저기 돌아다니면서 찾은 자료입니다.
따로 편집은 하지 않았구요
어디어디 자료인지 기억이 ㅡㅡ;; 죄송합니다.
티맥스 관련 자료도 포함되어 있습니다.

----------------------------------------------------------------------

특정IP로 broadcasting이 가능한지요?

두가지 방법이 가능합니다.

1. tpbroadcast를 사용하는 경우
`tpbroadcast(nodename, usrname, cltid ,,,) ;
이런 식으로 사용가능하므로,
usrname이나 cltid를 사용하면, 특정한 client에게 메세지를 보낼 수 있습니다.
usrname과 cltid는 tpstart에서 사용한 이름입니다.

그리고, nodename, usrname과 cltid에는 wildcard (*, ?)를 사용할 수 있어서 특정 그룹의 user들에게도 메세지를 동시에 보낼 수 있습니다.

2. tpsendtocli를 사용하는 경우
예를 들면, 아래과 같습니다.
tpsendtocli()의 인자를 살펴보시면 알겠지만,
첫번째 인자가 client id입니다. 그러므로 tpsendtocli를 사용하기 전에 tpgetclid() 함수를 수행하여 client id를 얻어야 됩니다.
tpgetclid()와 tpsendtocli()는 같은 서비스내에서 수행되어야 할 필요는 없습니다.

SERVICE(TPSVCINFO *msg)
{
int ret, clid;
char *buf;
buf = (char *)tpalloc("STRING", NULL, 0);
if (buf==NULL) { error processing }
strcpy(buf, msg->data);
/* data process…*/
clid = tpgetclid();
if (clid==-1) { /* error processing */}
ret=tpsendtocli(clid, (char *)buf, 0, 0);
if (ret==-1) { error processing }
tpreturn(TPSUCCESS, 0, 0, 0);
}


==================================================================================


비요청메시지에 관한 질문


특정 업무에 관련된 클라이언트에게 비요청 메세지를 보내실려면 클라이언트에서 tpsubscribe()를 이용하여 이벤트를 등록하시고 서비스 프로그램에서 tppost를 이용하여 등록한 이벤트에 비 요청 메세지를 보낼 수 있습니다.

아래는 클라이언트 sample입니다. tpsubscribe()를 하여 이벤트를 등록하시고 tpsetunsol()로 수신 받을 함수를 등록하면 됩니다.

#include
#include

void * get_unsol(char *, long, long);

main(int argc, char *argv[])
{
int ret;
int pid, index;
char *sndbuf, *rcvbuf;
TPSTART_T *tpinfo;
long sndlen, rcvlen, sndlen1, rcvlen1;

if(argc != 2) {
printf("Usage: ?0string\n", argv[0]);
exit(1);
}

tpinfo = (TPSTART_T *)tpalloc("TPSTART", NULL, sizeof(TPSTART_T));
if (tpinfo == NULL) {
fprintf(stderr, "tpalloc failed !<-tpinfo\n");
exit(1);
}

strcpy(tpinfo->usrname, "Kim Dae-In");

/* ----- Tmax connection ----- */
if (tpstart(tpinfo) == -1)

{
fprintf(stderr, "tpstart fail errno = ?", tperrno);
exit(1);
}
printf("tpstart-ok!\n");

ret = tpsubscribe("EVENT1", NULL, NULL, 0);
if (ret < 0) {
fprintf(stderr, "subscribe fail errno = ?", tperrno);
tpend();
exit(1);
}
tpsetunsol(get_unsol);

if ((sndbuf = tpalloc("STRING", NULL, 0)) == NULL) {
fprintf(stderr, "tpalloc failed:sndbuf\n");
tpend();
exit(1);
}

if ((rcvbuf = tpalloc("STRING", NULL, 0)) == NULL) {
fprintf(stderr, "tpalloc failed:rcvbuf\n");
tpfree(rcvbuf);
tpend();
exit(1);
}

/* ----- move data to send buffer ---- */
strcpy(sndbuf, argv[1]);

/* ----- service call svcname = SSYNC ----- */
ret = tpcall("POSTSVC", (char *)sndbuf, 0, (char **)&rcvbuf, &rcvlen, 0);
if (ret < 0) {
fprintf(stderr, "tpcall fail errno = ?", tperrno);
tpfree((char *)sndbuf);
tpfree((char *)rcvbuf);
tpend();
exit(1);
}
printf("tpcall OK\n");

printf("rcvbuf after service request:?", rcvbuf);

tpfree(sndbuf);
tpfree(rcvbuf);
tpend();
}

void *
get_unsol(char *data, long len, long flag)
{
printf("unsolicited data = ?", data);
}

tpgetclid()함수는 특정 클라이언트에게 tpsendtocli()를 이용해서 비 요청 메세지를 보내고자 할 경우에 사용하거나 또는 업무 적으로 사용할 경우에 사용할 수 있습니다.

답변이 늦어서 대단히 죄송합니다.

========================================================================


현재 Tmax에 접속되어 있는 클라이언트들 중에서 특정 업무에 관련된 클라이언트에게 비요청 메시지를 보낼려고 하는데, 이럴 경우에는 클라이언트의 ID가 항상 일정해야하거든요
> 그런데, 클라이 언트 ID 가 Tmax에 접속된 순번으로 부여가 되는 것 같더라고요
>
> 혹시, 클라이언트의 ID를 사용자가 임의로 주어 항상 일정게유지 시킬수 있는지요?
> 부여 되었다면 Tmax는 그 정보를 어느곳에 저장해 두는지 정말 궁금합니다.
>
> 그리고 Tmax 서버에서 클라이언트에게 메시지를 보낼때 클라이언트의 어떤 정보를 가지고 메시지를 보내는지요....
>
> 마지막으로 클라이언트의 ID를 얻어내는 tpgetcliid() 라는 API함수는 어떻게 동작되고 어떻게 사용 되는지도 부탁드릴께요.... 메뉴얼에는 그 함수를 이용해서 클라이언트의 아이디를 얻어낸다고 만 기술이 되있어서....

==================================================================================

클라이언트에서 비요청 메세지를 받기 위해서는 클라이언트가 Tmax와 연결할때 비요청 메세지를 받겠다는 flags를 설정해야만 비요청 메세지를 받을 수 있습니다.

flags 값으로는 보통 TPUNSOL_HND와 TPUNSOL_POLL를 사용하는데
TPUNSOL_HAD를 설정하면 tpsetunsol()를 이용하여 비 요청 메세지를 수신받을 함수를 등록하여 사용할 수 있습니다. 즉 비 동기형으로 데이터를 수신 받을 수 있습니다.
그러나 TPUNSOL_POLL를 tpsetunsol() 함수를 사용할 수 없고, 비요청 메세지를 받을려면 tpgetunsol() 함수를 이용하여 동기형으로 받아야 합니다.

====================================================================================


참고하시기 바랍니다.

lsndbuf = tpalloc("TPSTART", "", 0)
If lsndbuf = 0 Then
MsgBox "send buffer allocation error" & gettperrno()
Exit Sub
End If
....

tpinfo.flags = TPUNSOL_POLL

lret = FilltpstartBuf(lsndbuf, tpinfo)

ret = tpstart(ByVal lsndbuf&)
If ret = -1 Then
lblComment.Caption = "tpstart error = " & gettperrno()
TmaxError ("tpstart")
Else
lblComment.Caption = "tpstart return value = " & ret
End If
...


> 비쥬얼베이직으로 클라이언트 프로그램을 만들었는데여..
> 서버에서 주는 비요청메세지를 받으려면...
> 비쥬얼베이직에서는 어떤 형식의 함수를 써야하나여?
> TPSTART_T 플래그를 받는것(TPUNSOL_HND)으로 하면 된다구 하던데....
> 제가 코딩한 부분은여..
>
> dim sss as tpstart_t
>
> sss.flags = tpunsol_hnd
>
> 이렇게 했는데여...
> 여기서 tpstart를 하기전에 버퍼할당을 먼저 해야 한다구 하는데여...
> 버퍼할당하구...
>
> tpstart에는 어떻게 플래그값을 넘겨조야 할까여?!

====================================================================================

[UNIX] Tuxedo에서 Broadcast Message보내기

Tuxedo에서 broadcast를 위하여 수행되는 함수입니다.
service내에 모두 기술되어 있으므로 tuxedo help를 참고하여 보시면 됩니다.
현재 사용되어지고 있는 부분으로 소스에 있다시피 CArray방식으로 작성되었습니다.
FML이나 View방식은 M/A하는 회사들이나 BEA의 홈페이지에 많이 나와 있으므로
다른 사이트를 참고하십시오.

/* test function */
void MESSAGE_BROADCAST(TPSVCINFO *svc)
{
int rv;
char *fout, bctime[31];
struct tm *tm_ptr;
long timeval;

if((fout=(char *)tpalloc("CARRAY", NULL, MAX_LENGTH))==(char *)NULL)
{
tpreturn(TPFAIL, 0, "F", 1, 0) ;
return;
}

time(&timeval);
tm_ptr = localtime(&timeval);
strftime(bctime, 30, "XXXXXXXXXX", tm_ptr);
sprintf(fout, "Broadcast Message ??", bctime, svc->len, svc->data);
rv = (NULL, NULL, NULL, fout, strlen(fout), 0L);
if(-1 == rv)
{
fprintf(stdout,"broadcast:획\n", tperrno, tpstrerror(tperrno)) ;
tpreturn(TPFAIL, 0, (char *)fout, strlen(fout), 0) ;
}
else
{
tpreturn(TPSUCCESS, 0, (char *)fout, strlen(fout), 0) ;
}
return;
}

=====================================================================================

67 Tmax Application Development Guide
2.2.5 비요청 메시지 관련 인터페이스
Tmax에서 서버는 클라이언트가 요청하지 않은 메시지를 클라이언트에게 일방적으로 보낼
수 있다. 이것은 Tmax에 접속되어 있는 클라이언트에게 알리고 싶은 메시지를 전달하고자
할 때 사용한다.
비요청 메시지를 받을 수 있는 클라이언트는 Tmax에 접속되어 있어야 하고, Tmax 접속 시
비요청 메시지를 받겠다고 플래그 값을 설정해야 한다.
Int tpbroadcast( char *lmid, char *usrname, char *cltname, char *data, long *len, long flags)
: 비요청 메시지를 보냄.
lmid : 메시지를 받을 대상이 되는 머신 이름
usrname : 메시지를 받을 대상이 되는 사용자 이름
cltname : 메시지를 받을 클라이언트 그룹
data : 메시지 Buffer
len : 메시지 Buffer의 길이
flags : 메세지 송신시 사용되는 옵션
TPNOBLOCK : 서비스나 서버의 실패에 대한 응답을 받지 않음
TPNOTIME : Blocking time-out을 무시함.
TPSIGRSTART : 시그널 캐취를 허가함.
이 함수는 클라이언트와 서버가 다른 클라이언트에게로 비요청 메시지를 보내고자 할 때
사용한다. 이 때 비요청 메시지를 받을 클라이언트는 Tmax에 접속되어 있어야 하며,
tpstart()에서 비요청 메시지를 받겠다는 플래그로 접속되어 있어야만 한다.
받을 대상이 되는 클라이언트는 cltname에 설정된다. cltname 정보는 tpstart() 호출시
TPSTART_T 구조체의 cltname에 설정된 값이다.
Ex)
...
ret = tpbroadcast(NULL, "user", “cli1”, (char *)msg->data, 0, 0);
if (ret < 0)
{
error processing routine
}
...
int tpsendtocli(int clid, char *data, long len, long flags)
clid : Tmax에서 얻은 클라이언트의 유일한 값
data : 보낼 Buffer에 대한 크기
len : Buffer 크기
flags : 메세지 송신시 사용되는 옵션
TPFLOWCONTROL : 클라이언트의 상태를 점검하고 다른 메시지를 요청
할 수 있는지 확인함.
TPUDP : 호출자가 데이터를 송신할 때, 송신할 내부 버퍼에 전달될
메세지가 가득 차서 보내지 못할 경우 데이터를 버려도됨.
TPUDP |TPFLOWCONTROL : TPFLOWCONTROL flag 와 비슷하지만 이
flag는 큐가 가득 찼을 경우 ?1이 아닌 일반적인 결과물을 return함.
TPNOBLOCK : 서비스나 서버의 실패에 대한 응답을 받지 않음
tpsendtocli()는 단지 서버에서만 사용할 수 있고, 클라이언트에서는 사용할 수 없다.
tpsendtocli()은 어떤 요청에 대한 응답을 전송하는 tpreturn()과는 달리 서버가
클라이언트에게 일방적으로 메시지를 전송하는데 사용한다.
clid는 tpgetcliid()라는 API를 써서 얻어낼 수 있고, 일방적인 메시지를 전달할 대상을
구별하는 값이다.
data는 보낼 Buffer의 포인터이고 len은 Buffer의 길이이다.
Ex)
...
int clid, ret;
...
clid = tpgetclid();
if (clid < 0)
{
error processing routine
}
...
ret = tpsendtocli(clid, unsolmsg, strlen(unsolmsg), 0);
if (ret < 0)
{
error processing routine
}


===================================================================================

- 65 - Tmax Reference Manual
tpbroadcast
이 름
tpbroadcast : 비요청 메시지 송수신 함수 (서버/클라이언트)
사용 방법
# include <atmi.h>
int tpbroadcast (char *lmid, char *usrname, char *cltname, char *data, long len, long
flags)
설 명
tpbroadcast()는 클라이언트나 서버가 Tmax 시스템에 등록된 클라이언트들에게 요청하
지 않은 메시지를 송신하는 함수이다. 메시지가 송신 가능한 클라이언트들은 tpstart()함
수로 이미 Tmax 시스템에 연결되어 있어야 하며, 이 때 클라이언트의 이름과 플래그가
알맞게 정의되어야 한다. 즉 비 요청 메시지를 받기 위해서는 비 요청 메시지를 받겠다
는 정보를 주어야 한다. tpstart() 시 사용하는 TPSTART_T 구조체의 플래그값을
TPUNSOL_POLL 이나 TPUNSOL_HND 로 설정해야만 비 요청 메시지를 받을 수 있다.
lmid, usrname, cltname 은 대상 클라이언트를 선택하는데 사용되는 논리적인 이름이다.
이름 지정에는 와일드 카드(wildcards) 문자들이 사용될 수 있다. usrname 과
cltname 은 설정되는 이름 중간에 ?나 *등의 와일드 카드가 들어갈 수 있으나 lmid 는
이름 전체를 대신하여 *만이 사용될 수 있다. 또한 NULL 값이 사용될 수 있는데, 이는
모든 클라이언트에 대응되는 와일드 카드로 동작한다. 길이가 0 인 스트링 인수는
스트링 길이가 0 인 클라이언트 이름과만 대응된다. lmid, usrname, cltname 의 길이는
15 자 이내여야한다. cltname 으로 사용되는 이름은, 클라이언트가 tpstart()를 이용하여
처음 Tmax 시스템에 연결할 때 등록하는 클라이언트 이름이다.
data 는 반드시 tpalloc()에 의해 이전에 할당된 버퍼를 사용하여야 한다. len 은 송신할
데이터 길이 이다. 만약, data 가 가리키는 버퍼가 특별한 길이 명시가 필요 없는 버퍼
유형(STRING, STRUCT, X_COMMON, X_C_TYPE)이라면 이 때 len 은 무시된다.(보통
0 이 사용된다) 또한 data 는 NULL 이 될 수 있으며 그 경우에도 len 은 무시된다.
flags 로 사용 가능한 값은 다음과 같다.
TPNOBLOCK
블로킹(blocking) 상황을 만나면(예를 들어, 내부 버퍼가 송신 메시지들로 가득
찬 경우), 요청이 송신되지 않는다.
TPNOTIME
TPNOTIME 플래그는 함수 호출자가 블로킹 타임아웃을 무시하고 응답이 수신
될 때까지 무한정 기다리겠다는 것을 의미한다. 그러나 트랜잭션 타임아웃
내에서 tpbroadcast()를 한 경우에는 여전히 트랜잭션 타임아웃이 적용된다
TPSIGRSTRT
시그널(signal) 인터럽트를 수용하고자 할 때 사용한다. 내부에서 시그널 인터럽
트가 발생하여 시스템 함수 호출이 방해될 때 시스템 함수 호출이 재실행된다.
만약, 이 플래그가 설정되지 않은 경우 시그널 인터럽트가 발생하였다면, 함수는
실패하고 tperrno 에 TPGOTSIG 가 설정된다.
반 환 값
tpbroadcast()는 실패할 경우 -1 을 return 하고, tperrno 에 에러 상황에 해당하는 값이
설정된다.
오 류
다음 상황에서 tpbroadcast()는 실패하고, 어떤 메시지도 클라이언트들에게 송신되지
-
않으며 tperrno 에 아래 값 중 하나가 설정된다
[TPEINVAL]
인수가 유효하지 않다. 예를 들어, 식별자 길이가 너무 길거나 플래그가
유효하지 않은 경우이다. lmid 를 잘못 사용한 경우, tpbroadcast()가 실패하고
TPEINVAL 을 return 하게 된다. 그러나 usrname 이나 cltname 이 잘못된 경우,
아무에게도 메시지가 전달되지 않고 단순히 성공인 것으로 수행된다.
[TPETIME]
TPNOBLOCK 이나 TPNOTIME 이 설정되지 않은 상태에서, 블로킹 타임아웃이
발생하였다.
[TPEBLOCK]
TPNOBLOCK 이 설정된 상태에서, 블로킹 상황이 발생하였다.
[TPEGOTSIG]
TPSIGRSTRT 가 설정되지 않은 상태에서, 시그널이 수신되었다.
[TPEPROTO]
tpbroadcast()가 부적절한 상황에서 호출되었다.
[TPESYSTEM]
Tmax 시스템에 에러가 발생하였다. 자세한 정보는 로그파일에 기록된다.
[TPEOS]
운영 시스템에 에러가 발생하였다.
참 조
tpalloc(), tpend(), tpstart()
예 제
#include <stdio.h>
#include <usrinc/atmi.h>
void main(int argc, char *argv[])
{
inr ret;
char *buf;
TPSTART_T *tpinfo;
tpinfo = (TPSTART_T *)tpalloc("TPSTART", NULL, sizeof(TPSTART_T));
if (tpinfo==NULL) { error processing }

strcpy(tpinfo->cltname, “cli1”);
strcpy(tpinfo->usrname, “navis”);
ret=tpstart(tpinf);
if (ret==-1) { error processing }

buf=tpalloc(“STRING”, NULL, 0);

if (buf==NULL) { error processing }

data process…

tpbroadcast("tmax", NULL, NULL, buf, 0, TPNOFLAGS);

data process....

tpfree(buf);
tpend();
}