HP OpenVMS Systems Documentation

Content starts here

HP TCP/IP Services for OpenVMS
Sockets API and System Services Programming


Previous Contents Index

2.5.1 Initiating a Connection (Sockets API)

To initiate a connection to a TCP server, use the connect() function. Example 2-7 shows a TCP client the connect() function to initiate a connection to a TCP server.

Example 2-7 Initiating a Connection (Sockets API)


#include <in.h>                     /* define internet related constants,   */
                                    /* functions, and structures            */
#include <inet.h>                   /* define network address info          */
#include <netdb.h>                  /* define network database library info */
#include <socket.h>                 /* define BSD socket api                */
#include <stdio.h>                  /* define standard i/o functions        */
#include <stdlib.h>                 /* define standard library functions    */
#include <string.h>                 /* define string handling functions     */


#define BUFSZ       1024                /* user input buffer size           */
#define PORTNUM     12345               /* server port number               */


void get_servaddr( void *addrptr )
{
    char buf[BUFSIZ];
    struct in_addr val;
    struct hostent *host;

    while ( TRUE )
        {
        printf( "Enter remote host: " );

        if ( fgets(buf, sizeof(buf), stdin) == NULL )
            {
            printf( "Failed to read user input\n" );
            exit( EXIT_FAILURE );
            }

        buf[strlen(buf)-1] = 0;

        val.s_addr = inet_addr( buf );

        if ( val.s_addr != INADDR_NONE )
            {
            memcpy( addrptr, &val, sizeof(struct in_addr) );
            break;
            }

        if ( (host = gethostbyname(buf)) )
            {
            memcpy( addrptr, host->h_addr, sizeof(struct in_addr) );
            break;
            }
        }
}


int main( void )
{
    int sockfd;
    struct sockaddr_in addr;

    /*
     * initialize socket address structure
     */

    memset( &addr, 0, sizeof(addr) );
    addr.sin_family = AF_INET;
    addr.sin_port   = htons( PORTNUM );
    get_servaddr( &addr.sin_addr );

    /*
     * create a socket
     */
(1)
    if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
        {
        perror( "Failed to create socket" );
        exit( EXIT_FAILURE );
        }

    /*
     * connect to specified host and port number
     */

    printf( "Initiated connection to host: %s, port: %d\n",
            inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)
          );
(2)
    if ( connect(sockfd, (struct sockaddr *) &addr, sizeof(addr)) < 0 )
        {
        perror( "Failed to connect to server" );
        exit( EXIT_FAILURE );
        }

    exit( EXIT_SUCCESS );
}

This example shows how to:

  1. Create a socket of type SOCK_STREAM .
  2. Initiate a connection on the socket.

2.5.2 Initiating a Connection (System Services)

To initiate a connection to a TCP server, use the $QIO system service with the IO$_ACCESS service and the p3 argument. The p3 argument of the IO$_ACCESS service is the address of an item_list_2 descriptor that points to the remote socket name.

Example 2-8 shows a TCP client using the IO_$ACCESS service to initiate a connection.

Example 2-8 Initiating a Connection (System Services)


#include <descrip.h>                /* define OpenVMS descriptors           */
#include <efndef.h>                 /* define 'EFN$C_ENF' event flag        */
#include <in.h>                     /* define internet related constants,   */
                                    /* functions, and structures            */
#include <inet.h>                   /* define network address info          */
#include <iodef.h>                  /* define i/o function codes            */
#include <netdb.h>                  /* define network database library info */
#include <ssdef.h>                  /* define system service status codes   */
#include <starlet.h>                /* define system service calls          */
#include <stdio.h>                  /* define standard i/o functions        */
#include <stdlib.h>                 /* define standard library functions    */
#include <string.h>                 /* define string handling functions     */
#include <stsdef.h>                 /* define condition value fields        */
#include <tcpip$inetdef.h>          /* define tcp/ip network constants,     */

                                    /* structures, and functions            */

#define BUFSZ       1024                /* user input buffer size           */
#define PORTNUM     12345               /* server port number               */


struct iosb
    {                                   /* i/o status block                 */
    unsigned short status;              /* i/o completion status            */
    unsigned short bytcnt;              /* bytes transferred if read/write  */
    void *details;                      /* address of buffer or parameter   */
    };

struct itemlst_2
    {                                   /* item-list 2 descriptor/element   */
    unsigned short length;              /* length                           */
    unsigned short type;                /* parameter type                   */
    void *address;                      /* address of item list             */
    };

struct sockchar
    {                                   /* socket characteristics           */
    unsigned short prot;                /* protocol                         */
    unsigned char type;                 /* type                             */
    unsigned char af;                   /* address format                   */
    };


void get_servaddr( void *addrptr )
{
    char buf[BUFSIZ];
    struct in_addr val;
    struct hostent *host;

    while ( TRUE )
        {
        printf( "Enter remote host: " );

        if ( fgets(buf, sizeof(buf), stdin) == NULL )
            {
            printf( "Failed to read user input\n" );
            exit( EXIT_FAILURE );
            }

        buf[strlen(buf)-1] = 0;

        val.s_addr = inet_addr( buf );

        if ( val.s_addr != INADDR_NONE )
            {
            memcpy( addrptr, &val, sizeof(struct in_addr) );
            break;
            }

        if ( (host = gethostbyname(buf)) )
            {
            memcpy( addrptr, host->h_addr, sizeof(struct in_addr) );
            break;
            }
        }
}


int main( void )
{
    struct iosb iosb;                   /* i/o status block                 */
    unsigned int status;                /* system service return status     */
    unsigned short channel;             /* network device i/o channel       */
    struct sockchar sockchar;           /* socket characteristics buffer    */
    struct sockaddr_in addr;            /* socket address structure         */
    struct itemlst_2 addr_itemlst;      /* socket address item-list         */
    $DESCRIPTOR( inet_device,           /* string descriptor with logical   */
                 "TCPIP$DEVICE:" );     /* name of network pseudodevice     */

    /*
     * initialize socket characteristics
     */

    sockchar.prot = TCPIP$C_TCP;
    sockchar.type = TCPIP$C_STREAM;
    sockchar.af   = TCPIP$C_AF_INET;

    /*
     * initialize socket address item-list descriptor
     */

    addr_itemlst.length  = sizeof( addr );
    addr_itemlst.type    = TCPIP$C_SOCK_NAME;
    addr_itemlst.address = &addr;

    /*
     * initialize socket address structure
     */

    memset( &addr, 0, sizeof(addr) );
    addr.sin_family = TCPIP$C_AF_INET;
    addr.sin_port   = htons( PORTNUM );
    get_servaddr( &addr.sin_addr );

    /*
     * assign i/o channel to network device
     */

    status = sys$assign( &inet_device,      /* device name                  */
                         &channel,          /* i/o channel                  */
                         0,                 /* access mode                  */
                         0                  /* not used                     */
                       );

    if ( !(status & STS$M_SUCCESS) )
        {
        printf( "Failed to assign i/o channel\n" );
        exit( status );
        }
    /*
     * create a socket
     */
(1)
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                       channel,             /* i/o channel                  */
                       IO$_SETMODE,         /* i/o function code            */
                       &iosb,               /* i/o status block             */
                       0,                   /* ast service routine          */
                       0,                   /* ast parameter                */
                       &sockchar,           /* p1 - socket characteristics  */
                       0,                   /* p2                           */
                       0,                   /* p3                           */
                       0,                   /* p4                           */
                       0,                   /* p5                           */
                       0                    /* p6                           */
                     );

    if ( status & STS$M_SUCCESS )
        status = iosb.status;

    if ( !(status & STS$M_SUCCESS) )
        {
        printf( "Failed to create socket\n" );
        exit( status );
        }

    /*
     * connect to specified host and port number
     */
(2)
    printf( "Initiated connection to host: %s, port: %d\n",
            inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)
          );

    status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                       channel,             /* i/o channel                  */
                       IO$_ACCESS,          /* i/o function code            */
                       &iosb,               /* i/o status block             */
                       0,                   /* ast service routine          */
                       0,                   /* ast parameter                */
                       0,                   /* p1                           */
                       0,                   /* p2                           */
                       &addr_itemlst,       /* p3 - remote socket name      */
                       0,                   /* p4                           */
                       0,                   /* p5                           */
                       0                    /* p6                           */
                     );

    if ( status & STS$M_SUCCESS )
        status = iosb.status;

    if ( !(status & STS$M_SUCCESS) )
        {
        printf( "Failed to connect to server\n" );
        exit( status );
        }

    exit( EXIT_SUCCESS );
}

This example shows how to:

  1. Create a socket using the IO$_SETMODE service.
  2. Initiate a connection using the IO$_ACCESS service.

2.6 Accepting a Connection (TCP Protocol)

A TCP server program must be able to accept incoming connection requests from client programs. The accept() function:

  • Returns the next completed connection from the completed connection queue.
  • Returns a new socket descriptor that is connected with the client, called the connected socket. There is one connected socket for each client connected to the server. The connected socket remains until the server is finished serving the client.

2.6.1 Accepting a Connection (Sockets API)

Example 2-9 shows how to use the accept() function.

Example 2-9 Accepting a Connection (Sockets API)


#include <in.h>                     /* define internet related constants,   */
                                    /* functions, and structures            */
#include <inet.h>                   /* define network address info          */
#include <netdb.h>                  /* define network database library info */
#include <socket.h>                 /* define BSD socket api                */
#include <stdio.h>                  /* define standard i/o functions        */
#include <stdlib.h>                 /* define standard library functions    */
#include <string.h>                 /* define string handling functions     */


#define SERV_BACKLOG    1               /* server backlog                   */
#define SERV_PORTNUM    12345           /* server port number               */


int main( void )
{
    int conn_sockfd;                    /* connection socket descriptor     */
    int listen_sockfd;                  /* listen socket descriptor         */

    unsigned int cli_addrlen;           /* returned length of client socket */
                                        /* address structure                */
    struct sockaddr_in cli_addr;        /* client socket address structure  */
    struct sockaddr_in serv_addr;       /* server socket address structure  */

    /*
     * initialize client's socket address structure
     */

    memset( &cli_addr, 0, sizeof(cli_addr) );

    /*
     * initialize server's socket address structure
     */

    memset( &serv_addr, 0, sizeof(serv_addr) );
    serv_addr.sin_family      = AF_INET;
    serv_addr.sin_port        = htons( SERV_PORTNUM );
    serv_addr.sin_addr.s_addr = INADDR_ANY;

    /*
     * create a listen socket
     */

    if ( (listen_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
        {
        perror( "Failed to create socket" );
        exit( EXIT_FAILURE );
        }

    /*
     * bind server's ip address and port number to listen socket
     */

    if ( bind(listen_sockfd,
              (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 )
        {
        perror( "Failed to bind socket" );
        exit( EXIT_FAILURE );
        }

    /*
     * set socket as a listen socket
     */

    if ( listen(listen_sockfd, SERV_BACKLOG) < 0 )
        {
        perror( "Failed to set socket passive" );
        exit( EXIT_FAILURE );
        }

    /*
     * accept connection from a client
     */

    printf( "Waiting for a client connection on port: %d\n",
            ntohs(serv_addr.sin_port)
          );

    cli_addrlen = sizeof(cli_addr);

    conn_sockfd = accept( listen_sockfd,     (1)
                          (struct sockaddr *) &cli_addr, (2)
                          &cli_addrlen       (3)
                        );
    if ( conn_sockfd < 0 )
        {
        perror( "Failed to accept client connection" );
        exit( EXIT_FAILURE );
        }

    printf( "Accepted connection from host: %s, port: %d\n",
            inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port)
          );

    exit( EXIT_SUCCESS );
}

In this example of an accept() function:

  1. listen_sockfd is the socket descriptor returned by the previous call to the socket() function. This socket is bound to an address with the bind() function. The listen() function changes the socket state from CLOSED to LISTEN (converts the unconnected socket to a passive socket).
  2. cli_addr receives the protocol address of the client.
  3. cli_addrlen is a value/result parameter that initially contains the size of the cli_addr structure. On return of the accept() function, the cli_addr structure contains the actual length, in bytes, of the socket address structure returned by the kernel for the connected socket.

2.6.2 Accepting a Connection (System Services)

To accept a connection request:

  1. Use the $ASSIGN system service to create a channel for the new connection.
  2. Use the $QIO system service using the IO$_ACCESS service with the IO$M_ACCEPT modifier.
    The p4 argument specifies the address of a word written with the channel number of the new connection. If p3 specifies a valid output buffer, the $QIO service returns the remote socket name.

    Note

    Specifying the IO$_ACCESS service is mandatory for TCP/IP. The IO$_ACCESS service uses the p4 argument only with the IO$M_ACCEPT modifier.

Example 2-10 shows a TCP server using the IO$_ACCESS service with the IO$M_ACCEPT modifier to accept incoming connection requests.

Example 2-10 Accepting a Connection (System Services)


#include <descrip.h>                /* define OpenVMS descriptors           */
#include <efndef.h>                 /* define 'EFN$C_ENF' event flag        */
#include <in.h>                     /* define internet related constants,   */
                                    /* functions, and structures            */
#include <inet.h>                   /* define network address info          */
#include <iodef.h>                  /* define i/o function codes            */
#include <netdb.h>                  /* define network database library info */
#include <ssdef.h>                  /* define system service status codes   */
#include <starlet.h>                /* define system service calls          */
#include <stdio.h>                  /* define standard i/o functions        */
#include <stdlib.h>                 /* define standard library functions    */
#include <string.h>                 /* define string handling functions     */
#include <stsdef.h>                 /* define condition value fields        */
#include <tcpip$inetdef.h>          /* define tcp/ip network constants,     */

                                    /* structures, and functions            */

#define SERV_BACKLOG    1               /* server backlog                   */
#define SERV_PORTNUM    12345           /* server port number               */

struct iosb
    {                                   /* i/o status block                 */
    unsigned short status;              /* i/o completion status            */
    unsigned short bytcnt;              /* bytes transferred if read/write  */
    void *details;                      /* address of buffer or parameter   */
    };

struct itemlst_2
    {                                   /* item-list 2 descriptor/element   */
    unsigned short length;              /* length                           */
    unsigned short type;                /* parameter type                   */
    void *address;                      /* address of item list             */
    };

struct itemlst_3
    {                                   /* item-list 3 descriptor/element   */
    unsigned short length;              /* length                           */
    unsigned short type;                /* parameter type                   */
    void *address;                      /* address of item list             */
    unsigned int *retlen;               /* address of returned length       */
    };

struct sockchar
    {                                   /* socket characteristics           */
    unsigned short prot;                /* protocol                         */
    unsigned char type;                 /* type                             */
    unsigned char af;                   /* address format                   */
    };


int main( void )
{
    struct iosb iosb;                   /* i/o status block                 */
    unsigned int status;                /* system service return status     */

    unsigned short conn_channel;        /* connect inet device i/o channel  */

    unsigned short listen_channel;      /* listen inet device i/o channel   */
    struct sockchar listen_sockchar;    /* listen socket characteristics    */

    unsigned int cli_addrlen;           /* returned length of client socket */
                                        /* address structure                */
    struct sockaddr_in cli_addr;        /* client socket address structure  */
    struct itemlst_3 cli_itemlst;       /* client socket address item-list  */

    struct sockaddr_in serv_addr;       /* server socket address structure  */
    struct itemlst_2 serv_itemlst;      /* server socket address item-list  */

    $DESCRIPTOR( inet_device,           /* string descriptor with logical   */
                 "TCPIP$DEVICE:" );     /* name of network pseudodevice     */
    /*
     * initialize socket characteristics
     */

    listen_sockchar.prot = TCPIP$C_TCP;
    listen_sockchar.type = TCPIP$C_STREAM;
    listen_sockchar.af   = TCPIP$C_AF_INET;

    /*
     * initialize client's item-list descriptor
     */

    memset( &cli_itemlst, 0, sizeof(cli_itemlst) );
    cli_itemlst.length  = sizeof( cli_addr );
    cli_itemlst.address = &cli_addr;
    cli_itemlst.retlen  = &cli_addrlen;

    /*
     * initialize client's socket address structure
     */

    memset( &cli_addr, 0, sizeof(cli_addr) );

    /*
     * initialize server's item-list descriptor
     */

    serv_itemlst.length  = sizeof( serv_addr );
    serv_itemlst.type    = TCPIP$C_SOCK_NAME;
    serv_itemlst.address = &serv_addr;

    /*
     * initialize server's socket address structure
     */

    memset( &serv_addr, 0, sizeof(serv_addr) );
    serv_addr.sin_family      = TCPIP$C_AF_INET;
    serv_addr.sin_port        = htons( SERV_PORTNUM );
    serv_addr.sin_addr.s_addr = TCPIP$C_INADDR_ANY;

    /*
     * assign i/o channels to network device
     */

    status = sys$assign( &inet_device,      /* device name                  */
                         &listen_channel,   /* i/o channel                  */
                         0,                 /* access mode                  */
                         0                  /* not used                     */
                       );

    if ( status & STS$M_SUCCESS )
        status = sys$assign( &inet_device,  /* device name                  */
                             &conn_channel, /* i/o channel                  */
                             0,             /* access mode                  */
                             0              /* not used                     */
                           );
    if ( !(status & STS$M_SUCCESS) )
        {
        printf( "Failed to assign i/o channel(s)\n" );
        exit( status );
        }

    /*
     * create a listen socket
     */
(1)
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                       listen_channel,      /* i/o channel                  */
                       IO$_SETMODE,         /* i/o function code            */
                       &iosb,               /* i/o status block             */
                       0,                   /* ast service routine          */
                       0,                   /* ast parameter                */
                       &listen_sockchar,    /* p1 - socket characteristics  */
                       0,                   /* p2                           */
                       0,                   /* p3                           */
                       0,                   /* p4                           */
                       0,                   /* p5                           */
                       0                    /* p6                           */
                     );

    if ( status & STS$M_SUCCESS )
        status = iosb.status;

    if ( !(status & STS$M_SUCCESS) )
        {
        printf( "Failed to create socket\n" );
        exit( status );
        }

    /*
     * bind server's ip address and port number to listen socket
     */
(2)
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                       listen_channel,      /* i/o channel                  */
                       IO$_SETMODE,         /* i/o function code            */
                       &iosb,               /* i/o status block             */
                       0,                   /* ast service routine          */
                       0,                   /* ast parameter                */
                       0,                   /* p1                           */
                       0,                   /* p2                           */
                       &serv_itemlst,       /* p3 - local socket name       */
                       0,                   /* p4                           */
                       0,                   /* p5                           */
                       0                    /* p6                           */
                     );

    if ( status & STS$M_SUCCESS )
        status = iosb.status;
    if ( !(status & STS$M_SUCCESS) )
        {
        printf( "Failed to bind socket\n" );
        exit( status );
        }

    /*
     * set socket as a listen socket
     */
(3)
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                       listen_channel,      /* i/o channel                  */
                       IO$_SETMODE,         /* i/o function code            */
                       &iosb,               /* i/o status block             */
                       0,                   /* ast service routine          */
                       0,                   /* ast parameter                */
                       0,                   /* p1                           */
                       0,                   /* p2                           */
                       0,                   /* p3                           */
                       SERV_BACKLOG,        /* p4 - connection backlog      */
                       0,                   /* p5                           */
                       0                    /* p6                           */
                     );

    if ( status & STS$M_SUCCESS )
        status = iosb.status;

    if ( !(status & STS$M_SUCCESS) )
        {
        printf( "Failed to set socket passive\n" );
        exit( status );
        }

    /*
     * accept connection from a client
     */

    printf( "Waiting for a client connection on port: %d\n",
            ntohs(serv_addr.sin_port)
          );
(4)
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                       listen_channel,      /* i/o channel                  */
                       IO$_ACCESS|IO$M_ACCEPT,
                                            /* i/o function code            */
                       &iosb,               /* i/o status block             */
                       0,                   /* ast service routine          */
                       0,                   /* ast parameter                */
                       0,                   /* p1                           */
                       0,                   /* p2                           */
                       &cli_itemlst,        /* p3 - remote socket name      */
                       &conn_channel,       /* p4 - i/o channel for new     */
                                            /*      connection              */
                       0,                   /* p5                           */
                       0                    /* p6                           */
                     );
    if ( status & STS$M_SUCCESS )
        status = iosb.status;

    if ( !(status & STS$M_SUCCESS) )
        {
        printf( "Failed to accept client connection\n" );
        exit( status );
        }

    printf( "Accepted connection from host: %s, port: %d\n",
            inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port)
          );

    exit( EXIT_SUCCESS );
}


Previous Next Contents Index