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