[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

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


Previous Contents Index

This example shows how to use the $ASSIGN and $QIOW system services to:

  1. Define a sockchar structure to contain the characteristics of the type of socket.
  2. Initialize the sockchar structure with the address family, protocol family and type of socket.
  3. Assign a channel to a network device using a string descriptor with the logical name of the network pseudodevice and a structure to receive the I/O channel.
  4. Create the socket with a call to SYS$QIOW specifying the IO$_SETMODE modifier to supply the channel and the socket characteristics.

2.3 Binding a Socket (Optional for Clients)

Binding a socket associates an IP address (that is, a 32-bit IPv4 address and a 16-bit TCP or UDP port number) with a socket. To bind a socket, specify an IP address and a port number for the socket.

With the TCP protocol, you can specify an IP address, a port number, both an IP address and port number, or neither.

If the application is using the UDP protocol and needs to receive incoming multicast or broadcast datagrams destined for a specific UDP port, see Section 2.10 for information about specifying the SO_REUSEPORT option when binding the socket.

For an example of binding a socket using the Sockets API, see Section 2.3.1. For an example of binding a socket using the OpenVMS system services, see Section 2.3.2.

2.3.1 Binding a Socket (Sockets API)

Example 2-3 shows an example of a TCP application using the bind() function to bind a structure.

Note

The process must have SYSPRV, BYPASS, or OPER privilege to bind port numbers 1 to 1023.

Example 2-3 Binding a Socket (Sockets API)


#include <in.h>                     /* define internet related constants,   */
                                    /* functions, and structures            */
#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 PORTNUM     12345               /* server port number               */


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 );
    addr.sin_addr.s_addr = INADDR_ANY;

    /*
     * create a socket
     */

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

    /*
     * bind ip address and port number to socket
     */

    if ( bind(sockfd,(1) (struct sockaddr *) &addr,(2) sizeof(addr)(3)) < 0 )
        {
        perror( "Failed to bind socket" );
        exit( EXIT_FAILURE );
        }

    exit( EXIT_SUCCESS );
}

In this example, the bind() function includes the following arguments:

  1. sockfd specifies the socket descriptor previously created with a call to the socket() function.
  2. addr specifies the address of the sockaddr_in structure that assigns a name to the socket.
  3. sizeof(addr) specifies the size of the sockaddr_in structure.

2.3.2 Binding a Socket (System Services)

Use the IO$_SETMODE or IO$_SETCHAR service of the $QIO system service to bind a socket.

Note

The process must have SYSPRV, BYPASS, or OPER privileges to bind port numbers 1 to 1023.

Example 2-4 shows how to bind a sockets using OpenVMS system services.

Example 2-4 Binding a Socket (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 <iodef.h>                  /* define i/o function codes            */
#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 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                   */
    };


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 );
    addr.sin_addr.s_addr = TCPIP$C_INADDR_ANY;

    /*
     * assign i/o channel to network device
     */
(1)
    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
     */
(2)
    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 );
        }

    /*
     * bind ip address and port number to socket
     */
(3)
    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                */
                       0,                   /* p1                           */
                       0,                   /* p2                           */
                       &addr_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 );
        }

    exit( EXIT_SUCCESS );
}

This example shows how to use OpenVMS system services to:

  1. Assign a network device.
  2. Bind a socket. The p1 argument specifies the socket characteristics.
  3. Bind the IP address and the port number to the socket. The p3 argument specifies the socket name.

2.4 Making a Socket a Listener (TCP Protocol)

Only server programs that use the TCP protocol need to set a socket to be a listener. This allows the program to receive incoming connection requests. As a connection-oriented protocol, TCP requires a connection; UDP, a connectionless protocol, does not.

The listen() function:

  • Converts the unconnected socket into a passive socket.
  • Changes the state of the socket to LISTEN.
  • Remains open for the life of the server.
  • Tells the kernel to accept incoming connections directed to this socket.

2.4.1 Setting a Socket to Listen (Sockets API)

Example 2-5 shows how a TCP server uses the listen() function to set a socket to listen for connection requests and to specify the number of incoming requests that can wait to be queued for processing.

Example 2-5 Setting a Socket to Listen (Sockets API)


#include <in.h>                     /* define internet related constants,   */
                                    /* functions, and structures            */
#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 BACKLOG     1                   /* server backlog                   */
#define PORTNUM     12345               /* server port number               */


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 );
    addr.sin_addr.s_addr = INADDR_ANY;

    /*
     * create a socket
     */

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

    /*
     * bind ip address and port number to socket
     */

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

    /*
     * set socket as a listen socket
     */
    if ( listen(sockfd, (1) BACKLOG (2) ) < 0 )
        {
        perror( "Failed to set socket passive" );
        exit( EXIT_FAILURE );
        }
    exit( EXIT_SUCCESS );
}

In this example of a listen() function:

  1. sockfd is the socket descriptor previously defined by a call to the socket() function.
  2. BACKLOG specifies that only one pending connection can be queued at any given time. The maximum number of connections is specified by the system configuration variable somaxconn . The default value for somaxconn is 1024. Refer to the HP TCP/IP Services for OpenVMS Tuning and Troubleshooting manual for how to display and change the somaxconn value dynamically.

2.4.2 Setting a Socket to Listen (System Services)

Example 2-6 shows how to use the IO$_SETMODE service to set the socket to listen for connection requests.

Example 2-6 Setting a Socket to Listen (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 <iodef.h>                  /* define i/o function codes            */
#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 BACKLOG     1                   /* server backlog                   */
#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                   */
    };


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 );
    addr.sin_addr.s_addr = TCPIP$C_INADDR_ANY;

    /*
     * 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 );
        }
    /*
     * bind ip address and port number to socket
     */
(2)
    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                */
                       0,                   /* p1                           */
                       0,                   /* p2                           */
                       &addr_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 );
        }
(3)
    /*
     * set socket as a listen socket
     */

    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                */
                       0,                   /* p1                           */
                       0,                   /* p2                           */
                       0,                   /* p3                           */
                       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 );
        }

    exit( EXIT_SUCCESS );
}

This example shows how to use three separate $QIO calls with the IO$_SETMODE service to:

  1. Create a socket, by specifying parameter p1.
  2. Bind a socket, by specifying parameter p3.
  3. Set the socket to passive (set listen on the socket) by specifying a value for parameter p4.

Alternatively, you can perform all three operations with one $QIO call.

2.5 Initiating a Connection (TCP Protocol)

A TCP client establishes a connection with a TCP server by issuing the connect() function. The connect() function initiates a three-way handshake between the client and the server.


Previous Next Contents Index