TCP/IP クライアント・プログラムの例を紹介しよう。
TCP/IPクライアントの処理の順序は
- socket 関数によって Socket識別子を生成する。
- setsockopt 関数によって Socket識別子のオプションを設定する。
- connect 関数によってサーバーへ接続する。
- send または recv 関数によって通信を開始する。
- 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 変換が
必要となることはいうまでもない。
