C/400

29. TCP/IP通信サービス・プログラムの作成

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