Phone:(705) 671-2652
    Fax:(705) 671-6127
   Email: tom@ontrak.net
Home Products Programming Applications Custom Designs Ordering News
    
ADRSockClient Example Code
 

overclnt.jpg (13,543 bytes)

CAVEAT: This document assumes that you are familiar with ANSI C programming. It is intended as a brief introduction to the concept of TCP/IP socket access to ADR cards. The sample code is provided for demonstration purposes only. Although the programs compile and run they are not a complete implementation.

This page describes the C code in the client program.

First we include the header files for all the API's and structures that we use.

#include <Winsock.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <memory.h>
#include <time.h>

The PrintHelp function provides some terse assistance for the user.

void PrintHelp(); // declaration of our help function

Now we declare our main procedure, our local variables and perform some prepartory steps similar to the server program. See the previous discussion about the server for details.

//
// ADR Sock Client main entry point
//
void main(int argc, char*argv[])
{
    BOOL bStillOK;
    int socket_id;      // id from socket function 
    int rcSockopt;      // return code from setsockopt 
    int rcConnect;      // return code from connect function 
    int rcSend;         // return code from write to socket  
    int rcRecv;         // return code from receive
    int turn_on_option_flag;
    int iRC;

    struct sockaddr_in sock_struc;
    struct hostent *hostptr;
    struct servent *servptr;
    time_t starttime;
    struct tm *today;
    WORD wVersionRequested;
    WSADATA wsaData;

    char node_name[32];
    char message[80];
    char datebuf[128];
    char timebuf[128];
    char conbuf[256];

    bStillOK = TRUE; // assume things are OK
    // first check args
    if (argc < 4 || argc > 4
        || !strcmp(argv[1],"-h") || !strcmp(argv[1],"-H")
        || !strcmp(argv[1],"-?") || !strcmp(argv[1],"/h")
        || !strcmp(argv[1],"/H") || !strcmp(argv[1],"/?")
        || !strcmp(argv[1],"help") || !strcmp(argv[1],"HELP"))
    {
        PrintHelp();
        bStillOK = FALSE;
    } // end if

    if (bStillOK)
    {
        time(&starttime);
        today = localtime (&starttime);
        strftime( datebuf, 128,
            "Today is %A, day %d of %B in the year %Y.\n",
            today );
        printf(datebuf);
        _strtime( timebuf );
        printf( "OS time:\t\t\t\t%s\n", timebuf );
		
        wVersionRequested = MAKEWORD (1,1);
        if((iRC = WSAStartup(wVersionRequested, &wsaData)) != 0)
        {
            printf ("startup failed, rc= %d\n", iRC);
            bStillOK = FALSE;
        } // end if
    } // endif 

The gethostbyname call looks up the IP address for a computer name. Here the server computer name is the first parameter of the ADRSockClient program. The IP address retrieved is the one that you associated with the server computer name in the Hosts file.

Sidebar: the gethostbyname call can also access Domain Name Services (DNS) to resolve an address.

if (bStillOK)
{
    strcpy (node_name, argv[1]); // name of server computer
    hostptr = gethostbyname (node_name);
    if (hostptr == (struct hostent *)NULL)
    {
        printf ("gethostbyname failed - check HOSTS file\n");
        bStillOK = FALSE;
    } // end if
} // end if

Next we create a socket and set its options. A real application has to check for errors returned by the socket and the setsockopt calls. Here, I simply proceed obliviously.

The setsockopt turns on the TCP_NODELAY option of the IPPROTO_TCP protocol. This means that messages are sent immediately and not combined in an attempt to fill up a packet.

The getservbyname call was described in the server-side discussion.

if (bStillOK)
{
    socket_id = socket (AF_INET, SOCK_STREAM,0);
		
    rcSockopt = setsockopt(socket_id, IPPROTO_TCP, 
            TCP_NODELAY,
            (char *) &turn_on_option_flag, 
            sizeof(turn_on_option_flag));
   
    servptr = getservbyname ("ADRlink", "tcp");
    if (servptr == (struct servent *)NULL)
    {
        printf ("cannot find service - check SERVICES file\n");
        bStillOK = FALSE;
    } // end if
} // end if

We load the sock_struc with the address information of the server and the port number for ADRlink. The connect call will try to establish communication with the server. The server will accept the connection as described in the server-side code. This establishes a socket connection with a client end-point identified by socket_id and a server endpoint identified by iSocket (in ADRSockSrv).

if (bStillOK)
{
    sock_struc.sin_family = hostptr->h_addrtype;
    memcpy((char *)&(sock_struc.sin_addr), hostptr->h_addr, 
            hostptr->h_length);
    sock_struc.sin_port = servptr->s_port;

    rcConnect = connect (socket_id, 
                         (struct sockaddr *)&(sock_struc),
                         sizeof(struct sockaddr));
    if (rcConnect == SOCKET_ERROR)
    {
        printf ("connect failed: rc is %d ", rcConnect);
        errno = WSAGetLastError();
        printf ("errno is %d\n",errno);
        bStillOK = FALSE;
    } // end if
} // end if

We build the message by concatenating the "repsonse expected" parameter and the "command" parameter. A trailing carriage return, "/r" terminates the message. The trailing carriage return indicates the end of the command to both the ADRSockSrv program and the ADR card.

The message is sent to the server over the socket connection.

if (bStillOK)
{
    strcpy(message,argv[2]);
    strcat(message,argv[3]);
    strcat(message,"\r");
    rcSend = send (socket_id, message, strlen(message), 0);
    if (rcSend == SOCKET_ERROR)
    {
        printf ("send failed: rc is %d ",rcSend);
        errno = WSAGetLastError();
        printf ("errno is %d\n",errno);
        bStillOK = FALSE;
    } // end if
} // end if

If we are expecting a reply then we issue a recv call on the socket connection. The recv call waits until a response is received or the socket connection is closed by the server.

if (bStillOK && (*argv[2] == 'y'|| *argv[2] == 'Y'))
{
    rcRecv = recv (socket_id, conbuf, BUFSIZ, 0);
    if (rcRecv == SOCKET_ERROR)
    {
        printf ("recv failed: rc is %d ",rcRecv);
        errno = WSAGetLastError();
        printf ("errno is %d\n",errno);
        bStillOK = FALSE;
    }
    else
    {
        conbuf[rcRecv] = '\0';
        printf("value received is: %s",conbuf);
    } // end if
} // end if

Finally, release the Windows Socket Architecture resources and exit.

    WSACleanup();
} // end main

 

To retrieve the source code used in this example via email,  send your name and address to tfortin@vianet.on.ca ( for our snail mail list ) and we will send the example via email.

Please indicate that you want the ADRSocketDemo.

 
    
Contact Information
Address Telephone Electronic Mail
Ontrak Control Systems Inc.
764 Notre Dame Ave., Unit #1
Tel: (705) 671-2652 General Information Sales or Support
Sudbury,Ontario Fax:(705) 671-6127 tom@ontrak.net
CANADA P3A 2T2    
              
Next-Day shipping anywhere in Continental U.S. via Fed-Ex
Copyright © 2012 ONTRAK CONTROL SYSTEMS 764 Notre Dame Ave, Unit #1 , Sudbury, Ontario, CANADA P3A 2T2  
"Quality serial Data Acquisition Interfaces"           PH. (705) 671-2652 FAX (705) 671-6127