예제
본 장에서는 간단한 애플리케이션 예제를 통해서 API의 기본적인 사용법과 전체적인 흐름을 설명한다.
1. 메시지 전송 프로그램
다음은 클라이언트와 서버에서 HMS API를 사용하여 메시지를 주고받는 간단한 프로그램 흐름이다.
-
클라이언트(Client1)는 string 타입의 버퍼에 입력된 문자열을 복사해서 서비스를 호출한다.
-
서버의 서비스 루틴에서는 이 문자열을 받아서 소문자를 대문자로 변경한 뒤 HMS로 메시지를 전송한다.
-
클라이언트(Client2)는 일정 시간이 지난 뒤 HMS로부터 메시지를 수신받는다.
1.1. HMS 환경설정
다음은 HMS 환경설정 파일 예제이다.
*DOMAIN hms SHMKEY = 74347, TPORTNO = 8808 *NODE Locke2 TMAXDIR ="/home/tmax5/tmax", APPDIR ="/home/tmax5/tmax/appbin/", MAXSESSION = 100 *SVRGROUP hms01 NODENAME = "Locke2", CPC = 1, SVGTYPE = "HMS", RESTART = Y, OPENINFO = "ORACLE_XA+Acc=P/scott/tiger+SesTm=60", HMSINDEX = 2, HMSMSGLIVE = 1, HMSMAXTHR = 2, HMSMAXDBTHR = 5, HMSNAME = hms_ora svg1 NODENAME = "Locke2" *HMS queue01 SVGNAME = hms01, BOOT = "WARM", TYPE = "QUEUE" topic01 SVGNAME = hms01, BOOT = "WARM", TYPE = "TOPIC" *SERVER svr SVGNAME = svg1 *SERVICE SVC SVRNAME = svr
1.2. 클라이언트 프로그램
다음은 클라이언트 프로그램 예제이다.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <usrinc/atmi.h> #include <usrinc/hmsapi.h> int main(int argc, char **argv) { char *sndbuf, *rcvbuf; long rcvlen, sndlen; HMS_SHND *sess; HMS_CHND *cons; hms_msg_t *msg; if (argc != 2) { printf("Usage : %s <message>\n\n", argv[0]); exit(1); } if (tmaxreadenv("tmax.env", "TMAX") == -1) { printf("error: tmaxreadenv() failed - %d\n", tperrno); exit(1); } if (tpstart((TPSTART_T *) NULL) == -1) { printf("error: tpstart() fail - %d\n", tperrno); exit(1); } if ((sndbuf = (char *)tpalloc("STRING", NULL, 0)) == NULL) { printf("error: sendbuf alloc failed !\n"); tpend(); exit(1); } if ((rcvbuf = (char *)tpalloc("STRING", NULL, 0)) == NULL) { printf("error: recvbuf alloc failed !\n"); tpfree((char *)sndbuf); tpend(); exit(1); } strcpy(sndbuf, argv[1]); if(tpcall("SVC", sndbuf, 0, &rcvbuf, &rcvlen, 0)==-1){ printf("error: Can't send request to service SVC\n"); tpfree((char *)sndbuf); tpfree((char *)rcvbuf); tpend(); exit(1); } sleep(5); /* RECV MESSAGE FROM HMS */ if ((sess = hms_create_session("hms01", 0, HMS_AUTO_ACK, 0)) == NULL) { printf("error: hms_create_session() failed tperrno = %d\n", tperrno); tpend(); exit(1); } if ((cons = hms_create_receiver(sess, "queue01", "cons01", NULL, NULL, 0)) == NULL) { printf("error: hms_create_receiver() failed tperrno = %d\n", tperrno); tpend(); exit(1); } /* ALLOCATION */ if ((msg = hms_alloc(sess, 1024)) == NULL) { printf("error: hms_alloc() failed tperrno = %d\n", tperrno); tpend(); exit(1); } /* RECV MESSAGE */ if (hms_recvex(cons, &msg, 5, 0) == -1) { printf("error: hms_recvex() failed tperrno = %d\n", tperrno); hms_free(msg); tpend(); exit(1); } /* GET BODY */ rcvlen = 1024; if (hms_get_body(msg, rcvbuf, &rcvlen) == -1) { printf("error: hms_get_body() failed tperrno = %d\n", tperrno); hms_free(msg); tpend(); exit(1); } printf("HMS MESSAGE : %s\n", rcvbuf); /* CLOSE RECEIVER */ if (hms_close_receiver(cons, 0) == -1) { printf("error: hms_close_receiver() failed tperrno = %d\n", tperrno); hms_free(msg); tpend(); exit(1); } /* CLOSE SESSION */ if (hms_close_session(sess, 0) == -1) { printf("error: hms_close_session() failed tperrno = %d\n", tperrno); hms_free(msg); tpend(); exit(1); } hms_free(msg); tpend(); return 0; }
1.3. 서버 프로그램
다음은 서버 프로그램의 예제이다.
<svr.c>
#include <stdio.h> #include <stdlib.h> #include <usrinc/atmi.h> #include <usrinc/hmsapi.h> HMS_SHND *sess = NULL; HMS_CHND *prod = NULL; int tpsvrinit(int argc, char **argv) { while(1) { sess = hms_create_session("hms01", 0, HMS_AUTO_ACK, 0); if (sess != NULL) { break; } if (tperrno != TPENOREADY) { printf("hms_create_session(hms01) : FAIL tperrno = %d\n", tperrno); return -1; } } prod = hms_create_sender(sess, "queue01", "prod_svc", 0); if (prod == NULL) { printf("hms_create_sender() : FAIL tperrno = %d\n", tperrno); return -1; } return 1; } int tpsvrdone() { hms_close_sender(prod, 0); hms_close_session(sess, 0); return 1; } SVC(TPSVCINFO *msg) { int n, i; hms_msg_t *hmsmsg = NULL; char *data = msg->data; int len = msg->len, asize; printf("SVC STARTED!\n"); /* TOUPPER */ for (i = 0; i < len; i++) data[i] = toupper(data[i]); /* ALLOCATION */ asize = len +1024; hmsmsg = hms_alloc(sess, asize); if (hmsmsg == NULL) { printf("hms_alloc : fail tperrno = %d\n", tperrno); tpreturn(TPFAIL, 0, NULL, 0, 0); } /* SET BODY */ n = hms_set_body(hmsmsg, data, len); if (n < 0) { hms_free(hmsmsg); printf("hms_set_body : fail tperrno = %d\n", tperrno); tpreturn(TPFAIL, 0, NULL, 0, 0); } /* SEND : hms01, persistent */ n = hms_sendex(prod, hmsmsg, HMS_DLV_PERSISTENT, 0, 0, 0); if (n < 0) { hms_free(hmsmsg); printf("hms_sendex(prod) : fail tperrno = %d\n", tperrno); tpreturn(TPFAIL, 0, NULL, 0, 0); } /* FREE */ hms_free(hmsmsg); printf("SVC SUCCESS!\n"); tpreturn(TPSUCCESS, 0, NULL, 0, 0); }
1.4. 프로그램 컴파일
클라이언트/서버 프로그램은 Tmax 애플리케이션을 컴파일하는 과정과 동일하게 컴파일한다.
프로그램 컴파일에 대한 자세한 내용은 Tmax Application Development Guide를 참고한다. |
2. 메시지 저장 프로그램
다음은 서버/클라이언트 프로그램에서 HMS 전달받은 메시지를 데이터베이스에 저장하는 프로그램의 흐름이다.
-
클라이언트는 사용자의 입력을 받아서 HMS로 Queue 타입의 메시지를 전송한다.
-
서버측에서는 비동기 세션을 통해 소비자(Consumer)를 생성하고 메시지가 전송될 경우 ASYNC 서비스가 이 메시지를 수신한다.
-
ASYNC 서비스는 수신받은 메시지를 데이터베이스에 Insert한다.
2.1. HMS 환경설정
다음은 HMS 환경설정에 대한 예제이다.
*DOMAIN hms SHMKEY = 74347, TPORTNO = 8808 *NODE Locke2 TMAXDIR ="/home/tmax5/tmax", APPDIR ="/home/tmax5/tmax/appbin/", MAXSESSION = 100 *SVRGROUP hms01 NODENAME = "Locke2", CPC = 1, SVGTYPE = "HMS", RESTART = Y, OPENINFO = "ORACLE_XA+Acc=P/scott/tiger+SesTm=60", HMSINDEX = 2, HMSMSGLIVE = 1, HMSMAXTHR = 2, HMSMAXDBTHR = 5, HMSNAME = hms_ora svg1 NODENAME = "Locke2", RESTART = N, OPENINFO = "ORACLE_XA+Acc=P/scott/tiger+SesTm=60", DBNAME = "ORACLE", TMSNAME = tms_ora, MINTMS = 1 *HMS queue01 SVGNAME = hms01, BOOT = "WARM", TYPE = "QUEUE" topic01 SVGNAME = hms01, BOOT = "WARM", TYPE = "TOPIC" *SERVER async SVGNAME = svg1, CLOPT = "-- -i" *SERVICE ASYNCSVC SVRNAME = async
2.2. 클라이언트 프로그램
다음은 클라이언트 프로그램 예제이다.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <usrinc/atmi.h> #include <usrinc/hmsapi.h> int main(int argc, char **argv) { long len; HMS_SHND *sess; HMS_PHND *prod; hms_msg_t *msg; char *data; int no; if (argc != 3) { printf("Usage : %s <no> <message>\n\n", argv[0]); exit(1); } if (tmaxreadenv("tmax.env", "TMAX") == -1) { printf("error: tmaxreadenv() failed - %d\n", tperrno); exit(1); } if (tpstart((TPSTART_T *) NULL) == -1) { printf("error: tpstart() fail - %d\n", tperrno); exit(1); } len = strlen(argv[2]); data = argv[2]; no = atoi(argv[1]); /* SEND MESSAGE TO HMS */ if ((sess = hms_create_session("hms01", 0, HMS_AUTO_ACK, 0)) == NULL) { printf("error: hms_create_session() failed tperrno = %d\n", tperrno); tpend(); exit(1); } if ((prod = hms_create_sender(sess, "queue01", "prod01", 0)) == NULL) { printf("error: hms_create_sender() failed tperrno = %d\n", tperrno); tpend(); exit(1); } /* ALLOCATION */ if ((msg = hms_alloc(sess, len + 1024)) == NULL) { printf("error: hms_alloc() failed tperrno = %d\n", tperrno); tpend(); exit(1); } /* SET BODY */ if (hms_set_body(msg, data, len) == -1) { printf("error: hms_set_body() failed tperrno = %d\n", tperrno); hms_free(msg); tpend(); exit(1); } /* SET PROPERTY */ if (hms_set_property(msg, "NO", HMS_INT, (char *)&no, sizeof(int)) == -1) { printf("error: hms_set_property() failed tperrno = %d\n", tperrno); hms_free(msg); tpend(); exit(1); } /* SEND MESSAGE */ if (hms_sendex(prod, msg, HMS_DLV_PERSISTENT, 0, 0, 0) == -1) { printf("error: hms_sendex() failed tperrno = %d\n", tperrno); hms_free(msg); tpend(); exit(1); } if (hms_close_sender(prod, 0) == -1) { printf("error: hms_close_sender() failed tperrno = %d\n", tperrno); hms_free(msg); tpend(); exit(1); } if (hms_close_session(sess, 0) == -1) { printf("error: hms_close_session() failed tperrno = %d\n", tperrno); hms_free(msg); tpend(); exit(1); } hms_free(msg); tpend(); return 0; }
2.3. 서버 프로그램
다음은 서버 프로그램 예제이다.
<async.pc>
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <usrinc/atmi.h> #include <usrinc/hmsapi.h> HMS_SHND *sess; HMS_CHND *cons; int svrinit_start = 0; void abend_callback(HMS_SHND *session) { printf("START ABEND_CALLBACK FUNCTION\n"); hms_close_session(session, 0); printf("hms_close_session success\n"); while (1) { sess = (HMS_SHND *) hms_create_async_session("hms01", abend_callback, 0); if (sess == NULL) { if (tperrno == TPENOREADY) { usleep(500000); continue; } printf("hms_create_session() : FAIL [%d]\n\n", tperrno); return; } break; } cons = (HMS_CHND *) hms_create_receiver(sess, "queue01", "consasync", NULL, "ASYNCSVC", 0); if (cons == NULL) { printf("hms_create_receiver() : FAIL tperrno = %d\n\n", tperrno); return; } printf("END ABEND_CALLBACK FUNCTION\n"); } int tpsvrinit(int argc, char **argv) { int c; while ((c = getopt(argc, argv, "i")) != EOF) { switch (c) { case 'i': svrinit_start = 1; break; } } if (svrinit_start == 1) { printf("ASYNC SERVICE svrinit()\n"); while(1) { sess = (HMS_SHND *) hms_create_async_session("hms01", abend_callback, 0); if (sess == NULL) { if (tperrno == TPENOREADY) { usleep(500000); continue; } printf("ASYNC SERVICE hms_create_async_session() failed, tperrno[%d]\n", tperrno); return; } break; } cons = (HMS_CHND *) hms_create_consumer(sess, "queue01", HMS_QUEUE, "consasync", "", "ASYNCSVC", 0); if (cons == NULL) printf("ASYNC SERVICE hms_create_consumer() failed, tperrno[%d]\n", tperrno); return -1; } printf("ASYNC SERVICE svrinit() success\n"); } return 1; } int tpsvrdone() { if (svrinit_start == 1) { printf("ASYNC SERVICE svrdone()\n"); hms_close_consumer(cons, 0); hms_close_session(sess, 0); } return 1; } /* DB INSERT */ EXEC SQL include sqlca.h; EXEC SQL begin declare section; int no; char message[128]; EXEC SQL end declare section; int DBInsert( int n, char *data ) { printf("UPDATE START!!!\n"); memset( message, 0x00, sizeof(message) ); no = n; strcpy(message, data); EXEC SQL insert into hmstest(no, message) values(:no, :message); if ( sqlca.sqlcode != 0 ){ printf( "insert failed sqlcode = %d\n",sqlca.sqlcode ); return -1; } return 1; } ASYNCSVC(TPSVCINFO *svc) { hms_msg_t *msg; char *data; long llen = 4096; int prop = 0; int type; printf("ASYNC SERVICE CALLED\n"); msg = (hms_msg_t *)svc->data; if ((data = (char *)tpalloc("CARRAY", NULL, 4096)) == NULL) { printf("ASYNC SERVICE tpalloc return failed. tperrno[%d]\n", tperrno); tpreturn(TPFAIL, TPFAIL_ACK, svc->data, svc->len, 0); } if (hms_get_body(msg, data, &llen) < 0) { printf("ASYNC SERVICE hms_get_body() return failed. tperrno[%d]\n", tperrno); tpreturn(TPFAIL, TPFAIL_ACK, svc->data, svc->len, 0); } data[llen] = '\0'; llen = sizeof(int); if (hms_get_property(msg, "NO", &type, (char *)&prop, &llen) < 0) { printf("ASYNC SERVICE hms_get_property() return failed. tperrno[%d]\n", tperrno); } printf("ASYNC SERVICE RECV MESSAGE, BODY[%s], PROPERTY[NO:%d]\n", data, prop); if (DBInsert(prop, data) == -1) tpreturn(TPFAIL, TPFAIL_ACK, svc->data, svc->len, 0); tpreturn(TPSUCCESS, 0, svc->data, svc->len, 0); }
2.4. 데이터베이스 스크립트
테이블 작성 스크립트
다음은 Oracle 테이블 작성 스크립트이다.
sqlplus scott/tiger << EOF create table hmstest ( no number(7), message char(128) ); EOF
테이블 및 데이터 출력 스크립트
다음은 Oracle 테이블 및 데이터 출력 스크립트이다.
sqlplus scott/tiger << EOF desc hmstest; select * from hmstest; select count(*) from hmstest; EOF
2.5. 프로그램 컴파일
서버/클라이언트 프로그램은 Tmax 애플리케이션을 컴파일하는 과정과 동일하게 컴파일한다.
프로그램 컴파일에 대한 자세한 내용은 Tmax Application Development Guide를 참고한다. |