RPG からでも CLP からでも呼び出して使用できる TCP/IP通信の C/400による
サービス・プログラムを紹介しよう。
これは実際、Chicago に使用されている製品と同じものである。
各プロシージャー関数は、TCP/IP通信の SOCKET API の使用方法の参考にも
なるものである。
0001.00 /********************************************************************* 0002.00 /* 0003.00 /* TCPMOD : TCP/IP API fuction module programm for Chicago 0004.00 /* 0005.00 /* Office Quattro Co.ltd 99.04.29 19:50:21 created 0006.00 /* this program will be called and binded by TCP400SVR CLP 0007.00 /* and present socket fuctions to parent program. 0008.00 /* 0009.00 /* create : CRTCMOD PANELWKR/TCPMOD 0010.00 /* CRTSRVPGM PANELWKR/TCPMOD TCPEXPORT 0011.00 /* 0012.00 /********************************************************************* 0013.00 #pragma comment(COPYRIGHT, "(C) OfficeQuattro Co,.Ltd Japan 1998. All 0014.00 #include <stdio.h> 0015.00 #include <stdlib.h> 0016.00 #include <string.h> 0017.00 #include <sys/types.h> 0018.00 #include <sys/socket.h> 0019.00 #include <netinet/in.h> 0021.00 #include <errno.h> 0022.00 #include <QMHSNDM.h> 0023.00 #include <qusec.h> 0024.00 #include <qusrjobi.h> 0025.00 #include <qclrdtaq.h> 0026.00 #include <qsnddtaq.h> 0027.00 #include <qrcvdtaq.h> 0028.00 0029.00 /*( Global Variable for socket descriptors and transaction information 0030.00 #define PORT 3005 0031.00 #define BufferLength 1492 0032.00 int l_ccsid = 0; /* Local System CCSID */ 0033.00 int r_ccsid = 0; /* Remote System CCSID */ 0034.00 int buffer_length = 0; /* Current buffer size */ 0035.00 int newfd = 0; /* socket descriptor */ 0036.00 int sockfd = 0; 0037.00 char* ascii_buffer = NULL; /* Pointer to buffer for conversation */ 0038.00 #define TRUE 0 0039.00 #define FALSE -1 0040.00 0041.00 /********************************************************************** 0042.00 /* << followings are program inner functions >> * 0043.00 /********************************************************************** 0044.00 0045.00 /*****************************************************/ 0046.00 /* SendMessage : SendPgmMessage to QSYSOPR */ 0047.00 /*****************************************************/ 0048.00 void SendMessage(int err_id)/* send error message to QSYSOPR */ 0049.00 { 0050.00 char msg_id7; 0051.00 char msg_fl_name20; 0052.00 char msg_data38; 0053.00 int msg_data_len; 0054.00 char msg_type10; 0055.00 char msg_queue10; 0056.00 int nbr_msgq; 0057.00 char reply_msgq20; 0058.00 char msg_key4; 0059.00 typedef struct{ 0060.00 int bytes_prov; 0061.00 int bytes_avail; 0062.00 char except_id7; 0063.00 char reserved1; 0064.00 char except_data50; 0065.00 } error_code; 0066.00 error_code err_code; 0067.00 err_code.bytes_prov = err_code.bytes_avail = 0; 0068.00 strncpy(msg_id, "CPF9898", 7); 0069.00 strncpy(msg_fl_name, "QCPFMSG *LIBL ", 20); 0070.00 strncpy(msg_data, "CHICAGO TCPMOD ERROR = ", 23); 0071.00 strncpy(reply_msgq, "*PGMQ ", 20); 0072.00 switch(err_id){/*SWITCH*/ 0073.00 case 1:strncat(msg_data, "FAILED IN SOCKET ", 24); 0074.00 break; 0075.00 case 2:strncat(msg_data, "FAILED IN BIND ", 24); 0076.00 break; 0077.00 case 3:strncat(msg_data, "FAILED IN LISTEN ", 24); 0078.00 break; 0079.00 case 4:strncat(msg_data, "FAILED IN ACCEPT ", 24); 0080.00 break; 0081.00 case 5:strncat(msg_data, "FAILED IN SPAWN ", 24); 0082.00 break; 0083.00 case 6:strncat(msg_data, "GIVESOCK DTALEN ", 24); 0084.00 break; 0085.00 case 7:strncat(msg_data, "GIVESOCK STREAM ", 24); 0086.00 break; 0087.00 case 8:strncat(msg_data, "GIVE DESCRIPTOR ERROR. ", 24); 0088.00 break; 0089.00 case 9:strncat(msg_data, "TAKESOCK GET JOBID ERROR", 24); 0090.00 break; 0091.00 case 10:strncat(msg_data, "TAKESOCK DESCRIPTOR GEN.", 24); 0092.00 break; 0093.00 }/*SWITCH*/ 0094.00 msg_data_len = 47; 0095.00 strncpy(msg_type, "*COMP ", 10); 0096.00 strncpy(msg_queue,"*SYSOPR ", 10); 0097.00 nbr_msgq = 1; 0098.00 0099.00 QMHSNDM(msg_id, msg_fl_name, msg_data, msg_data_len, msg_type, 0100.00 msg_queue, nbr_msgq, reply_msgq, msg_key, &err_code); 0101.00 0102.00 } 0103.00 /********************************************************************** 0104.00 /* << followings are this program's main function >> * 0105.00 /********************************************************************** 0106.00 0107.00 /*****************************************************/ 0108.00 /* TCPSVROPEN : Open TCP/IP as server */ 0109.00 /*****************************************************/ 0110.00 void TCPSVROPEN(int *newfd) 0111.00 { 0112.00 /*( Variable ans structure definitions )*/ 0113.00 int rc, length = sizeof(int); 0114.00 int addrlen = 0; 0115.00 char bufferBufferLength; 0116.00 struct sockaddr_in iaddr; 0117.00 /*-------------------------------------------------------*/ 0118.00 /* socket : Get a socket descriptor */ 0119.00 /*-------------------------------------------------------*/ 0120.00 sockfd = socket(AF_INET, SOCK_STREAM, 0); 0121.00 if(sockfd <0){/*cannot get sock*/ 0122.00 SendMessage(1); 0123.00 perror("socket() failed");exit(-1); 0124.00 }/*cannot get sock*/ 0125.00 /*-------------------------------------------------------*/ 0126.00 /* bind : bind address to the socket */ 0127.00 /*-------------------------------------------------------*/ 0128.00 memset(&iaddr, 0x00, sizeof(struct sockaddr_in)); 0129.00 iaddr.sin_family = AF_INET; 0130.00 iaddr.sin_port = htons(PORT); /* PORT No. set*/ 0131.00 iaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* any address OK */ 0132.00 rc = bind(sockfd, (struct sockaddr*)&iaddr, sizeof(iaddr)); 0133.00 if(rc < 0){/*failed*/ 0134.00 SendMessage(2); 0135.00 perror("bind() failed");exit(-1); 0136.00 }/*failed*/ 0137.00 0138.00 /*----------------------------------------------------- 0139.00 /* listen : wait for new client's call 0140.00 /* Up to 5 clients can be queued 0141.00 /*----------------------------------------------------- 0142.00 rc = listen(sockfd, 10); 0143.00 if(rc < 0){/*failed*/ 0144.00 SendMessage(3); 0145.00 perror("listen() failed");close(sockfd);exit(-1 0146.00 }/*failed*/ 0147.00 /*----------------------------------------------------- 0148.00 /* accept : accept new client's request 0149.00 /* from parent, should block 0150.00 /*----------------------------------------------------- 0151.00 *newfd = accept(sockfd, (struct sockaddr*)NULL, NULL); 0152.00 if(*newfd < 0){/*failed*/ 0153.00 SendMessage(4); 0154.00 perror("accept() failed");close(sockfd);exit(-1 0155.00 }/*failed*/ 0156.00 /*( don't close newfd and sockfd )*/ 0157.00 return; /*( not exit(0) )*/ 0158.00 } 0159.00 /*****************************************************/ 0160.00 /* TCPSEND : Send data to remote system */ 0161.00 /*****************************************************/ 0162.00 void TCPSEND(int *newfd, char *buffer, int *length, int *rc) 0163.00 { 0164.00 *rc = send(*newfd, buffer, *length, 0); 0165.00 if(*rc < 0){/* write err */ 0166.00 perror("write() failed");exit(-1); 0167.00 }/* write err */ 0168.00 return; /*( not exit(0) )*/ 0169.00 } 0170.00 /*****************************************************/ 0171.00 /* TCPRECV : Read data from remote system */ 0172.00 /*****************************************************/ 0173.00 void TCPRECV(int *newfd, char *buffer, int *length, int *rc) 0174.00 { 0175.00 char wrk_bufferBufferLength; 0176.00 int wrk_rc; 0177.00 int zero_rcv = 0; 0178.00 0179.00 *rc = recv(*newfd, buffer, *length, 0); 0180.00 if(*rc < 0) exit(-1); 0181.00 if(*rc < *length && *rc > 0){/*read*/ 0182.00 wrk_rc = *rc; 0183.00 while(wrk_rc < *length){/*while*/ 0184.00 memset(wrk_buffer, 0, sizeof(wrk_buffer)); 0185.00 *length -= wrk_rc; 0186.00 wrk_rc = FALSE; 0187.00 wrk_rc = recv(*newfd, wrk_buffer, *length, 0); 0188.00 if(wrk_rc == 0) zero_rcv++; 0189.00 if(wrk_rc < 0 || zero_rcv == 3){/*fail*/ 0190.00 printf("failed in re-receive・n");exit(-1);}/*fail*/ 0191.00 buffer*rc = 0x00;wrk_bufferwrk_rc = 0x00; 0192.00 memcpy(&buffer*rc, wrk_buffer, wrk_rc); 0193.00 *rc += wrk_rc; 0194.00 buffer*rc = 0x00; 0195.00 }/*while*/ 0196.00 }/*read*/ 0197.00 return; /*( not exit(0) )*/ 0198.00 0199.00 } 0200.00 /*****************************************************/ 0201.00 /* TCPCLOSE : Close TCP/IP Conversation */ 0202.00 /*****************************************************/ 0203.00 void TCPCLOSE(int *newfd) 0204.00 { 0205.00 close(*newfd); 0206.00 /* exit(0)*/;/*( end of this program )*/ 0207.00 } 0208.00 /*****************************************************/ 0209.00 /* TAKESOCKET : Takedescriptor from parent process */ 210.00 /*****************************************************/ 211.00 #define ID_LEN 16 212.00 int getjobid(char *jobid) 213.00 { 214.00 struct Qwc_JOBI0100 jobinfo; 215.00 Qus_EC_t error = {sizeof(Qus_EC_t)}; 216.00 QUSRJOBI(&jobinfo, sizeof(jobinfo), "JOBI0100", 217.00 "* ", 218.00 " ", 219.00 &error); 220.00 if(error.Bytes_Available != 0) return -1; 221.00 memcpy(jobid, jobinfo.Int_Job_ID, ID_LEN); 222.00 return 0; 223.00 } 224.00 short int TAKESOCKET(char jobid16) 225.00 { 226.00 int newfd; 227.00 int rc; 228.00 struct iovec iov1; 229.00 struct msghdr msg; 230.00 char buffer80; 0231.00 0232.00 /* system("CRTDTAQ DTAQ(QUSRTEMP/TCPDTAQ) MAXLEN(20)");*/ 0233.00 QCLRDTAQ("TCPDTAQ ", "QUSRTEMP "); 0234.00 /* if((rc = getjobid(jobid)) < 0){ 0235.00 SendMessage(9); 0236.00 return -1;} */ 0237.00 /* while(1){ */ 0238.00 QSNDDTAQ("TCPDTAQ ", "QUSRTEMP ", ID_LEN, jobid); 0239.00 /* 0240.00 if((newfd = takedescriptor(NULL)) < 0){ 0241.00 SendMessage(10); 0242.00 printf("takedescriptor( ) failed・n"); 0243.00 close(newfd); 0244.00 return -1; 0245.00 } 0246.00 */ 0247.00 memset(&msg, 0, sizeof(msg)); 0248.00 memset(iov, 0, sizeof(iov)); 0249.00 iov0.iov_base = buffer; 0250.00 iov0.iov_len = sizeof(buffer); 0251.00 msg.msg_iov = iov; 0252.00 msg.msg_iovlen = 1; 0253.00 msg.msg_accrights = (char*)&newfd; 0254.00 msg.msg_accrightslen = sizeof(newfd); 0255.00 rc = recvmsg(newfd, &msg, 0); 0256.00 if(rc < 0){ 0257.00 perror("recvmsg failed"); 0258.00 close(newfd); 0259.00 exit(-1); 0260.00 } 0261.00 /* printf("TAKESOCKET SUCCESS SOCKID = %d・n", newfd); */ 0262.00 /* 0263.00 if(newfd > 0) break; 0264.00 } 0265.00 */ 0266.00 return (short)(newfd); 0267.00 } 0268.00 /*****************************************************/ 0269.00 /* GIVESOCKET : Takedescriptor from parent process */ 0270.00 /*****************************************************/ 0271.00 int GIVESOCKET(int sockfd) 0272.00 { 0273.00 /* int sockid; */ 0274.00 int rc; 0275.00 char jobid_dqID_LEN; 0276.00 _Decimal(5,0) data_len = ID_LEN; 0277.00 /* system("CRTDTAQ DTAQ(QUSRTEMP/TCPDTAQ) MAXLEN(20)");*/ 0278.00 QRCVDTAQ("TCPDTAQ ", "QUSRTEMP ", &data_len, jobid_dq, 10); 0279.00 /* printf("get jobid_dq = %x・n", jobid_dq); */ 0280.00 if(data_len != ID_LEN){ 0281.00 SendMessage(6); 0282.00 printf("QRCVDTAQ failed・n");return -1; 0283.00 } 0284.00 /* 0285.00 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ 0286.00 SendMessage(7); 0287.00 printf("socket() failed・n");return -1; 0288.00 } 0289.00 */ 0290.00 if((rc = givedescriptor(sockfd, jobid_dq)) < 0){ 0291.00 SendMessage(8); 0292.00 printf("givedescriptor() failed・n"); 0293.00 return -1; 0294.00 } 0295.00 /* printf("GIVESOCKET SUCCESS SOCKFD = %d・n", sockfd);*/ 0296.00 close(sockfd); 0297.00 return 0; 0298.00 }
0001.00 STRPGMEXP PGMLVL(*CURRENT) 0002.00 EXPORT SYMBOL("TCPSVROPEN") 0003.00 EXPORT SYMBOL("TCPSEND") 0004.00 EXPORT SYMBOL("TCPRECV") 0005.00 EXPORT SYMBOL("TCPCLOSE") 0006.00 EXPORT SYMBOL("TAKESOCKET") 0007.00 EXPORT SYMBOL("GIVESOCKET") 0008.00 ENDPGMEXP