User Datagram Protocol (UDP) client

/******************************************************************/
/* This is a datagram socket client sample program which sends a  */
/* request to the server program and receives an echo message     */
/* back from the server.                                          */
/******************************************************************/
#include <tpf/tpfeq.h>
#include <tpf/tpfio.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/socket.h>

qxyg(char *argv[], u_short num_arg)
{

#define NUM_PARAMETER         5

#define return_ok             0
#define return_error         -1

#define no                    0
#define yes                   1

  /***********************************************************/
  /* This is the maximum message size that will be supported */
  /***********************************************************/
  const max_msg_size = 32 * 1024;

  struct sockaddr_in client_sockaddr_in;  /* Client internet addr */
  struct sockaddr_in server_sockaddr_in;  /* Server internet addr */

  char  msg = '0';
  char *recv_client_message;
  char *send_client_message;

  int client_sock;
  int msg_lost;
  int msg_recv;
  int msg_resend;
  int msg_resyn;
  int rc;
  int redo_select;
  int sockaddr_in_length;
  int sock_list[1];
  /********************/
  /** Argument List  **/
  /********************/
  int dest_ip;
  int dest_port;
  int num_msg;
  int siz_msg;
  int num_rsend;

  /*******************************************************************/
  /* Check the input argument list. If the number of arguments is    */
  /* incorrect, print out the help message.                          */
  /*******************************************************************/

  if (num_arg != NUM_PARAMETER)
  {
    printf("Invalid parameter(s) :\n");
    printf("ztest sock client datagram block <IP addr> <port #> \
                              <no. of msg> <msg size> <resend>\n");
    printf("ip addr     -  Server's IP address\n");
    printf("port #      -  Server's port number\n");
    printf("num of msg  -  Number of messages to be sent to \
                           the server \n");
    printf("msg size    -  Size of each message to be sent\n");
    printf("resend      -  Number of times to resend the lost message \
                           \n\n");
    exit(0);
  }
  else
  {
    /************************************************************/
    /* Extract the IP address, port number, number of messages, */
    /* size of each message, and number of resends.             */
    /************************************************************/
    dest_ip   = inet_addr(argv[0]);
    dest_port = atoi(argv[1]);
    num_msg   = atoi(argv[2]);
    siz_msg   = atoi(argv[3]);
    num_rsend = atoi(argv[4]);
  }
  if (siz_msg < 0)
     printf("qxyg: %d is an invalid message size\n",siz_msg);

  /****************************************************************/
  /* Create send/receive buffer based on user defined buffer size.*/
  /****************************************************************/
  send_client_message = (char *)malloc(max_msg_size);
  recv_client_message = (char *)malloc(max_msg_size);

  msg_resend = 0;
  msg_resyn  = 0;
  msg_lost   = 0;
  sockaddr_in_length = sizeof(struct sockaddr_in);

  /****************************/
  /* Create a datagram socket.*/
  /****************************/
  client_sock = socket(AF_INET,SOCK_DGRAM,17);
  if (client_sock == return_error)
  {
    printf("qxyg: Error in opening a datagram socket\n");
    exit(0);
  }

  /***********************************/
  /* Bind a local name to the socket.*/
  /***********************************/
  client_sockaddr_in.sin_family      = AF_INET;
  client_sockaddr_in.sin_port        = 0;
  client_sockaddr_in.sin_addr.s_addr = 0;
  rc = bind(client_sock,(struct sockaddr *)&client_sockaddr_in,
            sockaddr_in_length);
  if (rc == return_error)
  {
    printf("qxyg: Error in binding - %d\n",sock_errno());
    (void)close(client_sock);
    exit(0);
  }

  /********************************************************/
  /* Set socket to send/receive more than max_buffer_size.*/
  /********************************************************/
  rc = setsockopt(client_sock,SOL_SOCKET,SO_SNDBUF,
  (char *)&max_msg_size,sizeof(max_msg_size));
  if (rc != return_ok)
  {
    printf("qxyg: Error in setsockopt-SO_SNDBUF-%d\n",sock_errno());
    (void)close(client_sock);
    exit(0);
  }

  /*******************************************************************/
  /* Define server's internet address which is used for sendto() and */
  /* recvfrom().                                                     */
  /*******************************************************************/
  server_sockaddr_in.sin_family      = AF_INET;
  server_sockaddr_in.sin_port        = dest_port;
  server_sockaddr_in.sin_addr.s_addr = dest_ip;

  rc = connect(client_sock,(struct sockaddr *)&server_sockaddr_in,
               sockaddr_in_length);
  if (rc == return_error)
  {
    printf("qxyg: Error in connecting - %d\n",sock_errno());
    (void)close(client_sock);
    exit(0);
  }


  /*******************************************************************/
  /* Get the client information, and print client/server data out.   */
  /*******************************************************************/
  rc = getsockname(client_sock,(struct sockaddr *)&client_sockaddr_in,
                   &sockaddr_in_length);
  if (rc != return_error)
  {
    printf("Client Information\n");
    printf("--------------------------------\n");
    printf("Client sock       - %d\n",client_sock);
    printf("Client IP address - %x\n",                                 \
           client_sockaddr_in.sin_addr.s_addr);
    printf("Client port #     - %d\n",client_sockaddr_in.sin_port);
    printf("Server IP address - %x\n",                                 \
           server_sockaddr_in.sin_addr.s_addr);
    printf("Server port #     - %d\n\n",server_sockaddr_in.sin_port);
  }

  /**************************************************/
  /* Set up the first message to send to the server.*/
  /**************************************************/
  (void)memset(send_client_message,msg,siz_msg);
  send_client_message[siz_msg - 1] = 0;

  /*******************************************************************/
  /* Set up the sock_list for select() - use it for testing time out.*/
  /*******************************************************************/
  sock_list[0] = client_sock;

  /************************************/
  /* Loop until all messages are sent.*/
  /************************************/
  for (msg_recv = 1; msg_recv <= num_msg;)
  {

    /********************************/
    /* Send a message to the server.*/
    /********************************/

    rc = send(client_sock,send_client_message,siz_msg,0);
    if (rc == return_error)
    {
      /***********************************************/
      /* If an error occurred, resend the message.   */
      /***********************************************/
      printf("qxyg: Error in sending message to server-try again- \
               %d\n",sock_errno());
      msg_resend++;
    }
    else
    {
      /**********************************************************/
      /* A message was successfully sent, so monitor the read.  */
      /* If a message arrives within 15 seconds, read it in.    */
      /* Otherwise, a message was lost, so send it again.       */
      /**********************************************************/
      redo_select = yes;
      for (;redo_select; )
      {
        rc = select(sock_list,1,0,0,15000);
        if (rc >= 1)
        {
          /**********************************************************/
          /* Read the message.  If there is a problem, resend again.*/
          /**********************************************************/
          rc = read(client_sock,recv_client_message,max_msg_size);
          if (rc == return_error)
          {
            printf("qxyg : Error in receiving message from server - \
                   %d\n", sock_errno());
            msg_resend++;
          }
          else
          {
            /*********************************************************/
            /* If the received message is correct, then process the  */
            /* message.  Otherwise, throw the message out and wait   */
            /* for the next incoming message.                        */
            /*********************************************************/
            if (*recv_client_message == msg)
            {
              printf("Recv Msg %d - len = %d Source address = %x\n",
                      msg_recv,rc,server_sockaddr_in.sin_addr.s_addr);
              msg_recv++;
              msg_lost += msg_resend;
              msg_resend = 0;
              redo_select = no;

              /***********************************/
              /* Set up the next message to send.*/
              /***********************************/
              msg ++;
              if (msg > '9')
              {
                msg = '0';
              }
              (void)memset(send_client_message,msg,siz_msg);
              send_client_message[siz_msg - 1] = 0;
            }
            else
            {
              printf("qxyg: Received unexpected data. 1st character = \
                      %c\n", *recv_client_message);
              msg_resyn++;
            }
          }
        }
        else
        {
          /***********************************************************/
          /* If a time-out or an error in select() occurred, resend  */
          /* the message.                                            */
          /***********************************************************/
          msg_resend++;
          redo_select = no;
          if (rc == 0)
            printf("qxyg: Possible lost message# %d .... resend\n",
                   msg_recv);
          else
          {
            printf("qxyg: error in select() - %d\n",sock_errno());
            printf("Server IP address - %x\n", \
                   server_sockaddr_in.sin_addr.s_addr);
            printf("Server port #     - %d\n\n",
                   server_sockaddr_in.sin_port);
            printf("Client terminates abnormally\n");
            rc = close(client_sock);
            if (rc == return_error)
            {
              printf("qxyg: Error in closing the socket - %d\n",
                     sock_errno());
            }
            exit(0);
          }
        } /* end of else (select) */
      }  /* end of for (;redo_select;) */
    }  /* end of else (sendto) */

    /****************************************************************/
    /* If the number of times we resent the message exceeds the     */
    /* resend count, terminate this program abnormally.             */
    /****************************************************************/
    if (msg_resend >= num_rsend)
    {
      printf("\n");
      printf("qxyg: MSG %d has been resent %d times without any \
              response from the server.\n",msg_recv,msg_resend);
      printf("This could be caused by busy server or unreachable IP add\
              ress or port number.\n");
      printf("Server IP address - %x\n", \
              server_sockaddr_in.sin_addr.s_addr);
      printf("Server port #     - %d\n\n", \
             server_sockaddr_in.sin_port);
      printf("Client terminates abnormally\n");
      (void)close(client_sock);
      exit(0);
    }
  }

  /*******************************************************************/
  /* Print out the status. Close down socket and exit this program   */
  /*******************************************************************/
  msg_recv--;
  printf("\n");
  printf("qxyg: MSG Send/Recv = %d, MSG Resyn = %d, Total MSG Lost = \
          %d\n\n", msg_recv,msg_resyn,msg_lost-msg_resyn);

  rc = close(client_sock);
  if (rc == return_error)
  {
    printf("qxyg: Error in closing the socket - %d\n",sock_errno());
    exit(0);
  }
  printf("Client terminates normally\n");
  printf("Server IP address - %x\n", \
           server_sockaddr_in.sin_addr.s_addr);
  printf("Server port #     - %d\n\n",server_sockaddr_in.sin_port);
  exit(0);
}