www.sas.com > Service and Support > Technical Support
 
Technical Support SAS - The power to know(tm)
  TS Home | Intro to Services | News and Info | Contact TS | Site Map | FAQ | Feedback


/*---------------------------------------------------------------------+
|                Copyright (c) 1996, SAS Institute Inc.                |
|                  Unpublished - All Rights Reserved                   |
|                      S A S / C   S A M P L E                         |
|                                                                      |
|         NAME: TCPOEC                                                 |
|     LANGUAGE: C                                                      |
|      PURPOSE: Demonstrate a TCP Client application that connects to  |
|               a TCPOED, an open edition daemon. The client           |
|               connects to TCPOED, then does a send() and recv().     |
|   MVS -                                                              |
|      COMPILE, LINK, and EXECUTE: SUBMIT prefix.SAMPLE.AUX(TCPOEC)    |
|               where "prefix" is the installation defined high-level- |
|               qualifier for the SAS/C product.                       |
|        NOTES: On the //EXEC statement add a: ,PARM.GO='host_name'    |
|               where "host_name" is an optional hostname value        |
|        NOTES: TCPOEC assumes a working TCP/IP environment on both    |
|               the local and remote hosts, refer to MISC NOTES.       |
|   TSO -                                                              |
|      COMPILE: LC370 CLIST - options ENXREF EXTNAME RENT              |
|         LINK: CLK370 CLIST                                           |
|      EXECUTE: call 'your.load.library(TCPOEC)' 'host_name'           |
|               where "host_name" is an optional hostname value        |
|        NOTES: TCPOEC assumes a working TCP/IP environment on both    |
|               the local and remote hosts. Refer to MISC NOTES:       |
|                                                                      |
|   OE  - In order to compile, link, and execute under the OE shell,   |
|         the source file should first be copied to an HFS directory.  |
|         You may use the following commands to move the program to    |
|         the HFS system:                                              |
|         ALLOC F(TCPOEC) DS('prefix.SAMPLE.C(TCPOEC)') SHR            |
|         ALLOC F(HFSFIL) PATH('/path/tcpoec.c') PATHDISP(KEEP,DELETE) |
|                  PATHMODE(SIRUSR,SIWUSR) PATHOPTS(ORDWR,OCREAT)      |
|         OCOPY INDD(TCPOEC) OUTDD(HFSFIL) TEXT PATHOPTS(USE)          |
|      NOTE: Refer to the Open Edition MVS User's Guide for more       |
|            details, SC23-3013-02                                     |
|                                                                      |
|      COMPILE/LINK: sascc370 -Krent -o /path/tcpoec /path/tcpoec.c    |
|      NOTE: Refer to the SAS/C Compiler and Library User's Guide,     |
|            4th Edition, Release 6.00, and the SAS/C Installation     |
|            Instructions for details on using the compiler and library|
|            under the OE Shell.                                       |
|      EXECUTE: TCPOEC host_name                                       |
|               where "host_name" is an optional hostname value        |
|        NOTES: TCPOEC assumes a working TCP/IP environment on both    |
|               the local and remote hosts. Refer to MISC NOTES:       |
|   CMS -                                                              |
|      COMPILE: LC370 EXEC - options ENXREF EXTNAME RENT               |
|         LINK: CLINK EXEC                                             |
|      EXECUTE: TCPOEC host_name                                       |
|               where "host_name" is an optional hostname value        |
|        NOTES: TCPOEC assumes a working TCP/IP environment on both    |
|               the local and remote hosts. Refer to MISC NOTES:       |
|   MISC NOTES: TCPOEC needs to be customized for the local TCP/IP     |
|               environment. The local information required by         |
|               TCPOEC is:                                             |
|               HOST_NAME - host name running TCPOED. Ensure           |
|                           the TCP/IP environment has been configured |
|                           for name resolution,                       |
|                           default is: "mvs"                          |
|               HOST_PORT - port TCPOED has been configured to do a    |
|                           listen(), default is 6177.                 |
|               HOST_CNT  - number of iterations TCPOEC will execute,  |
|                           default is: 20                             |
|               HOST_TOK  - Token sent to TCPOED child process.        |
|               The keywords and values are customized by #define's    |
|               immediately following the #include statements below:   |
+---------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>

/*-------------------------------------------------------------------------+
| function prototypes                                                      |
+-------------------------------------------------------------------------*/
int init_sock(struct sockaddr_in *sa);
char *build_tok(void);
int send_data(int sockfd, char *buffer, int buf_len);
int recv_int(int sock_fd, int len);
char *recv_data(int sock_fd, int len);

/*-------------------------------------------------------------------------+
| Customize the values below to identify the host and port as configured   |
| for the tcpoed application, token, and number of iterations.             |
+-------------------------------------------------------------------------*/
#define HOST_NAME  "sdcesa"    /* Host name running TCPOED            */
#define HOST_PORT  6177        /* tcpoed "well known port"            */
#define HOST_CNT   10          /* Number of iterations for TCPOEC     */
#define HOST_TOK   "childtok"  /* Token sent to TCPOED child process  */
#define TOK_MAX     8          /* Token size                          */

#define BUF_SIZE    8192       /* Default TCPIP databufferpoolsize    */

main(int argc, char *argv[])
{
struct hostent *hp;            /* gethostbyname() structure           */
struct sockaddr_in sa;         /* connect() structure                 */
int i, recv_rc, send_rc, sockfd;
int sock_go;                   /* when enabled, issue socket calls    */
char *message, *h_name, *h_tok;

/*-------------------------------------------------------------------------+
| call gethostbyname() with the HOST_NAME or argv[1]                    l  |
+-------------------------------------------------------------------------*/
if (argc < 2)
  h_name = HOST_NAME;
else
  h_name = argv[1];

hp = gethostbyname(h_name);
if (!hp)
   {
   printf("unable to resolve host name: %s\n",h_name);
   return (-1);
   }

h_tok = build_tok();
if (h_tok == NULL)
   {
   printf("unable to build token\n");
   return (-1);
   }

/*-------------------------------------------------------------------------+
| initialize the sockaddr_in structure                                     |
+-------------------------------------------------------------------------*/
memset(&sa,'\0',sizeof(sa));  /* initialize "sa"                      */
sa.sin_family = AF_INET;
sa.sin_port = htons(HOST_PORT);
sa.sin_addr.s_addr = *(unsigned long *) hp->h_addr;

/*-------------------------------------------------------------------------+
| print values used to connect to daemon                                   |
+-------------------------------------------------------------------------*/
printf("\nUsing the following values to connect to tcpoed\n");
printf("IP address: %s\n",inet_ntoa(sa.sin_addr));
printf("Port number: %d\n",sa.sin_port);
printf("Execution count: %d\n\n",HOST_CNT);

/*-------------------------------------------------------------------------+
| Do the work:  issue a socket(), connect(), send() and recv(). If any     |
| socket fuction fails, set sock_go=0, and call socktrm().                 |
+-------------------------------------------------------------------------*/
for (i=1; i <= HOST_CNT; i++)
   {
   printf("Iteration number: %d\n", i);
   sock_go = 1;
   sockfd = init_sock(&sa);
   if (sockfd < 0)
      sock_go = 0;

/*------------------------------------------------------------------------+
| send_data() - with socket descriptor, h_tok value, and length           |
+------------------------------------------------------------------------*/
   if (sock_go)
   {
   send_rc = send_data(sockfd, h_tok, strlen(h_tok));
   if (send_rc < 0)
      sock_go = 0;
   }

/*------------------------------------------------------------------------+
| recv() - get the message length - first four bytes of data              |
+------------------------------------------------------------------------*/
   if (sock_go)
   {
   recv_rc = recv_int(sockfd, sizeof(int));
   if (recv_rc < 0)
      sock_go = 0;
   }

/*------------------------------------------------------------------------+
| recv() - get the message and print                                      |
+------------------------------------------------------------------------*/
   if (sock_go)
   {
   message = recv_data(sockfd, recv_rc);
   if (message == NULL)
      sock_go = 0;
   else
      printf("data received ==> %s\n",message);
   }

/*-------------------------------------------------------------------------+
| issue a close() after each socket connection is complete. A mis-behaved  |
| application could leave the socket open and let the OS clean-up the      |
| socket, at environment termination. Keeping the socket open may cause    |
| buffer or storage "anomalies".                                           |
+-------------------------------------------------------------------------*/
   if (sock_go)
   {
      close(sockfd);
   }

/*-------------------------------------------------------------------------+
| if sock_go is not enabled an error occured. When on MVS or CMS           |
| issue socktrm(), else exit with an error.                                |
+-------------------------------------------------------------------------*/
   if (!sock_go)
   #if defined(OSVS) | defined(CMS)
      socktrm();
   #else
      exit(-1);
   #endif

   }  /* end of for() loop */

printf("tcpoec complete\n");
return(0);
}


/*-------------------------------------------------------------------------+
| create a socket, connect to server and return socket number              |
+-------------------------------------------------------------------------*/
int init_sock(struct sockaddr_in *sa)
{
int sockfd;
sockfd = socket(AF_INET,SOCK_STREAM,0);
if (sockfd == -1)
   {
   perror("socket call failed");
   return(-1);
   }

if (connect(sockfd, sa, sizeof(struct sockaddr_in)) == -1)
   {
   perror("connect () failed");
   return(-1);
   }

return(sockfd);
}


/*-------------------------------------------------------------------------+
| build a token, translate if required and return token to caller          |
+-------------------------------------------------------------------------*/
char *build_tok()
{
char *h_tok;
int s_len;
#if defined(OSVS) | defined(CMS)
   int si;                        /* used for htoncs()                */
#endif

h_tok =  (char * ) calloc(TOK_MAX + 1, sizeof(char));
if (h_tok == NULL)
   return(NULL);

strncpy(h_tok,HOST_TOK,TOK_MAX);
s_len = strlen(h_tok);
/*-------------------------------------------------------------------------+
| When running on MVS or CMS convert HOST_TOK from a host character set    |
| to a network character set, EBCDIC to ASCII                              |
+-------------------------------------------------------------------------*/
   #if defined(OSVS) | defined(CMS)

      for ( si = 0; si < s_len; si++)
          h_tok[si] = htoncs(h_tok[si]);
   #endif

return(h_tok);
}


/*-------------------------------------------------------------------------+
| send data to server, return length sent or an error                      |
+-------------------------------------------------------------------------*/
int send_data(int sockfd, char *buffer, int buf_len)
{
int msg_len;

msg_len = send(sockfd, buffer, buf_len, 0);
if (msg_len <0)
   {
   perror("send() call failed");
   return(-1);
   }

return(msg_len);
}


/*-------------------------------------------------------------------------+
| read an int from the socket and return the value or -1                   |
+-------------------------------------------------------------------------*/
int recv_int(int sock_fd, int len)
{
int *ptr, recv_rc, bytes_rem, ret_val;

ret_val = 0;
ptr = &ret_val;
bytes_rem = len;

while (bytes_rem > 0)
  {
  recv_rc = recv(sock_fd, ptr, bytes_rem, 0);
  if (recv_rc <= 0 )
     {
     perror("recv() failed");
     return(-1);
     }
  else
     {
     bytes_rem -= recv_rc;
     ptr += recv_rc;
     }
  }

ret_val = ntohl(ret_val);
return(ret_val);
}


/*-------------------------------------------------------------------------+
| read data from the socket, convert to ebcdic if required, return         |
| NULL or a pointer to the data received.                                  |
+-------------------------------------------------------------------------*/
char *recv_data(int sock_fd, int len)
{
char *message, *ptr;
int recv_rc, bytes_rem;
#if defined(OSVS) | defined(CMS)
  int xi;
#endif

message = (char * ) malloc(len + 1);
if (message == NULL)
  {
  printf("recv_data() malloc failed\n");
  return(NULL);
  }

memset(message, '\0', len + 1);
ptr = message;
bytes_rem = len;

while (bytes_rem > 0)
  {
  recv_rc = recv(sock_fd, ptr, bytes_rem, 0);
  if (recv_rc <= 0 )
     {
     perror("recv() failed");
     return(NULL);
     }
  else
     {
     bytes_rem -= recv_rc;
     ptr += recv_rc;
     }
  }

#if defined(OSVS) | defined(CMS)
    for ( xi = 0; xi < len; xi++)
        message[xi] = ntohcs(message[xi]);
#endif

return(message);
}


Copyright (c) 2000 SAS Institute Inc. All Rights Reserved.
Terms of Use & Legal Information | Privacy Statement