TCP/IP

27. TCP/IP Socket通信クライアント

TCP/IP クライアント・プログラムの例を紹介しよう。

TCP/IPクライアントの処理の順序は

  1. socket 関数によって Socket識別子を生成する。
  2. setsockopt 関数によって Socket識別子のオプションを設定する。
  3. connect 関数によってサーバーへ接続する。
  4. send または recv 関数によって通信を開始する。
  5. close 関数によって Socketをクローズして終了する。
【 SOCKCLT: SOCKET による TCP/IPクライアント ( C/400) 】
/********************************************************************** 
/*                                                                      
/*   SOCKCLT : SOCK     CLIENT                                          
/*                                                                      
/********************************************************************** 
#include <stdio.h>                                                      
#include <stdlib.h>                                                     
#include <string.h>                                                     
#include <sys/socket.h>                                                 
#include <sys/types.h>                                                  
#include <netinet/in.h>                                                 
#include <netinet/tcp.h>                                                
#include <arpa/inet.h>                                                  
#include <errno.h>                                                      
                                                                        
#define TRUE         0                                                  
#define FALSE       -1                                                  
typedef struct {                                                        
   int  BYTESPRO;                                                       
   int  BYTESAVL;                                                       
   char MSGID[7];                                                       
   char RESRVD;                                                         
   char EXCPDATA[100];                                                  
} ERRSTRUCTURE;     /* Define the error return structure            */  
ERRSTRUCTURE  errcode;/* Error Code Structure for RCVMSG      */        
char addr[11] = "192.168.1.1";                                          
int PORT = 400;                                                         
                                                                        
void  INZSR(void);                                                      
void  err_log(char* msg, int opt, char* function, int line);            
                                                                        
void main(void){                                                        
   int sockfd, len, rc;                                                 
  struct sockaddr_in iaddr;                                             
   char buff[48];                                                       
                                                                        
   printf("** SOCKCLT **n");                                           
   getchar();                                                           
   INZSR();                                                             
  /*-------------------------------------------------------*/           
  /*         socket : Get a socket descriptor              */           
  /*-------------------------------------------------------*/          
  if((sockfd = socket(AF_INET, SOCK_STREAM, 0 )) < 0){                 
     perror("SOCKET"); getchar(); exit(0);                             
  }                                                                    
  /*-----------------------------------------------------------*/      
  /* connect: connect to the server using a set of port number */      
  /*-----------------------------------------------------------*/      
  memset(&iaddr, 0x00, sizeof(struct sockaddr_in));                    
  iaddr.sin_family = AF_INET;                                          
  iaddr.sin_port  = htons(PORT); /* PORT no set*/                      
  iaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* any address OK */      
  rc = connect(sockfd, (struct sockaddr *)&iaddr, sizeof(iaddr));      
  if(rc < 0){                                                          
     perror("CONNECT"); getchar(); exit(0);                            
  }                                                                    
                                                                       
  /*-----------------------------------------------------------*/      
  /*   send a message to the server using secure session       */      
  /*-----------------------------------------------------------*/      
  memset(buff, 0, sizeof(buff));                                       
  strcpy(buff, "* CLIENT 1ST MESSAGE USING SOCKET");                   
  len = strlen(buff);                                               
  rc = send(sockfd, buff, len, 0);                                  
  if(rc != len){                                                    
     if(rc < 0){                                                    
       perror("SEND"); getchar(); exit(0);                          
     }                                                              
     else{                                                          
       printf("SEND did not all datan");                           
       getchar(); exit(0);                                          
     }                                                              
  }                                                                 
  else{                                                             
     printf("SEND OK = %sn", buff);                                
  }                                                                 
  /*-----------------------------------------------------------*/   
  /*   receive the message from the server using SOCKET        */   
  /*-----------------------------------------------------------*/   
  memset(buff, 0, sizeof(buff));                                    
  rc = recv(sockfd, buff, len, 0);                                  
  if(rc < 0){                                                       
       perror("RECV"); getchar(); exit(0);                          
  }                                                           
     printf("RECV  OK = %sn", buff);                         
   close(sockfd);                                             
                                                              
    printf("**************************************n");       
    printf("*   SOCKCLT  SUCCESSFULLY COMPLETE ! *n");       
    printf("**************************************n");       
   getchar();                                                 
}                                                             
/****************/                                            
void  INZSR(void)                                             
/****************/                                            
 {                                                            
                                                              
    errcode.BYTESPRO = errcode.BYTESAVL = 0;                  
 }                                                            
/********************************************************/    
void  err_log(char* msg, int opt, char* err_at, int line)     
/********************************************************/    
{                                                             
    fprintf(stderr, "%sn", msg);                             
     fprintf(stderr, " ->ERR AT = %s, LINE = %dn", err_at, line);  
     if(opt == TRUE)                                                
       fprintf(stderr, "%sn", strerror(errno));                    
 }
【 解説 】

コンパイルは

CRTBNDC MYOBJLIB/SOCKCLT SRCFILE(MYSRCLIB/QCSRC) AUT(*ALL)

実行は2つの5250エミュレータを起動しておく必要がある。
まず、最初のエミュレータのコマンド入力画面において

CALL MYOBJLIB/SOCKSVR + [実行]

を行うと* SOCKSVR * が表示されて停止するので、さらに実行キーを押すと

     
       ** SOCKSVR ** 
     >               
       * SOCKET OK   
       * SOCKOPT OK  
       * BIND OK     
       * LISTEN OK 
 

のようにして LISTEN で停止してクライアントからの要求に対して待機することがわかる。

次に別の5250エミュレータを起動してコマンド入力画面から

CALL MYOBJLIB/SOCKCLT + 【 実行】

を行うと* SPCKCLT * が表示されて停止するので、さらに実行キーを押して継続すると


        ** SOCKCLT **                                
      >                                              
        SEND OK = * CLIENT 1ST MESSAGE USING SOCKET  
        RECV  OK = * SOCK SERVER *                   
        **************************************       
        *   SOCKCLT  SUCCESSFULLY COMPLETE ! *       
        **************************************
 

のように表示されてサーバーから * SOCK SERVER * というメッセージが受信される。

一方、サーバー側の画面に戻ってみると、サーバー側でも


       ** SOCKSVR **                                    
     >                                                  
       * SOCKET OK                                      
       * SOCKOPT OK                                     
       * BIND OK                                        
       * LISTEN OK                                      
       * ACCEPT OK                                      
       * RECV OK = * CLIENT 1ST MESSAGE USING SOCKET    
       * SEND OK                                        
       **************************************           
       *  SOCKSVR   SUCCESSFULLY COMPLETE ! *           
       **************************************
 

と表示されていて、クライアントからの「* CLIENT 1ST MESSAGE USING SOCKET」が
受け取られていることがわかる。
これは PORT=400 による iSeries 内での通信の例であるが IPアドレスや PORT を変更すれば、
どのような「相手」であってもTCP/IPで通信することができるのである。

ただし、この例では iSeriesどうしであり、相手が PCサーバーなどであれば EBCDIC/ASCII 変換が
必要となることはいうまでもない。